feat: add foundation for a BOSS CLI

This commit is contained in:
mrjvs 2025-09-03 22:20:50 +02:00
parent a4a20852f6
commit 616a24d8d7
8 changed files with 172 additions and 2 deletions

15
package-lock.json generated
View File

@ -14,6 +14,7 @@
"@pretendonetwork/grpc": "^1.0.6",
"@typegoose/auto-increment": "^3.6.1",
"boss-js": "github:PretendoNetwork/boss-js",
"commander": "^14.0.0",
"dicer": "^0.3.1",
"dotenv": "^16.4.7",
"express": "^5.1.0",
@ -4496,6 +4497,15 @@
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
"integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -12902,6 +12912,11 @@
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
"integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",

View File

@ -9,7 +9,8 @@
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"build": "tsup && tsc --noEmit",
"start": "node --enable-source-maps dist/server.js"
"start": "node --enable-source-maps dist/server.js",
"cli": "node --enable-source-maps dist/cli/cli.js"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.723.0",
@ -17,6 +18,7 @@
"@pretendonetwork/grpc": "^1.0.6",
"@typegoose/auto-increment": "^3.6.1",
"boss-js": "github:PretendoNetwork/boss-js",
"commander": "^14.0.0",
"dicer": "^0.3.1",
"dotenv": "^16.4.7",
"express": "^5.1.0",

22
src/cli/apps.cmd.ts Normal file
View File

@ -0,0 +1,22 @@
import { Command } from 'commander';
import { getCliContext } from './utils';
const listCmd = new Command('ls')
.description('List all apps in BOSS')
.action(async () => {
const ctx = getCliContext();
const apps = await ctx.grpc.listKnownBOSSApps({});
console.log(apps);
});
const viewCmd = new Command('view')
.description('Look up a specific BOSS app')
.argument('<id>', 'BOSS app ID to lookup')
.action(async () => {
console.log('Test');
});
export const appCmd = new Command('app')
.description('Manage all the apps in BOSS')
.addCommand(listCmd)
.addCommand(viewCmd);

13
src/cli/cli.ts Normal file
View File

@ -0,0 +1,13 @@
import { program as baseProgram } from 'commander';
import { taskCmd } from './tasks.cmd';
import { fileCmd } from './files.cmd';
import { appCmd } from './apps.cmd';
const program = baseProgram
.name('BOSS')
.description('CLI to manage and view BOSS data')
.addCommand(appCmd)
.addCommand(taskCmd)
.addCommand(fileCmd);
program.parseAsync(process.argv).catch(console.error);

44
src/cli/files.cmd.ts Normal file
View File

@ -0,0 +1,44 @@
import { Command } from 'commander';
const listCmd = new Command('ls')
.description('List all task files in BOSS')
.argument('<app_id>', 'BOSS app to search in')
.argument('<task_id>', 'Task to search in')
.action(async () => {
console.log('Test');
});
const viewCmd = new Command('view')
.description('Look up a specific task file')
.argument('<app_id>', 'BOSS app that contains the task')
.argument('<task_id>', 'Task that contains the task file')
.argument('<id>', 'Task file ID to lookup')
.action(async () => {
console.log('Test');
});
const createCmd = new Command('create')
.description('Create a new task file')
.argument('<app_id>', 'BOSS app to store the task file in')
.argument('<task_id>', 'Task to store the task file in')
.action(async () => {
console.log('Test');
});
const deleteCmd = new Command('delete')
.description('Delete a task file')
.argument('<app_id>', 'BOSS app that contains the task')
.argument('<task_id>', 'Task that contains the task file')
.argument('<id>', 'Task file ID to delete')
.action(async () => {
console.log('Test');
});
// TODO add updateCmd
export const fileCmd = new Command('file')
.description('Manage all the task files in BOSS')
.addCommand(listCmd)
.addCommand(createCmd)
.addCommand(deleteCmd)
.addCommand(viewCmd);

40
src/cli/tasks.cmd.ts Normal file
View File

@ -0,0 +1,40 @@
import { Command } from 'commander';
const listCmd = new Command('ls')
.description('List all tasks in BOSS')
.argument('<app_id>', 'BOSS app to search in')
.action(async () => {
console.log('Test');
});
const viewCmd = new Command('view')
.description('Look up a specific task')
.argument('<app_id>', 'BOSS app ID that contains the task')
.argument('<id>', 'Task ID to lookup')
.action(async () => {
console.log('Test');
});
const createCmd = new Command('create')
.description('Create a new task')
.argument('<app_id>', 'BOSS app to store the task in')
.action(async () => {
console.log('Test');
});
const deleteCmd = new Command('delete')
.description('Delete a task')
.argument('<app_id>', 'BOSS app ID that contains the task')
.argument('<id>', 'Task ID to delete')
.action(async () => {
console.log('Test');
});
// TODO add updateCmd
export const taskCmd = new Command('task')
.description('Manage all the tasks in BOSS')
.addCommand(listCmd)
.addCommand(createCmd)
.addCommand(deleteCmd)
.addCommand(viewCmd);

34
src/cli/utils.ts Normal file
View File

@ -0,0 +1,34 @@
import { BOSSDefinition } from '@pretendonetwork/grpc/boss/boss_service';
import { createChannel, createClient, Metadata } from 'nice-grpc';
import type { BOSSClient } from '@pretendonetwork/grpc/boss/boss_service';
export type CliContext = {
grpc: BOSSClient;
};
export function getCliContext(): CliContext {
const grpcHost = process.env.PN_BOSS_CLI_GRPC_HOST ?? '';
const grpcKey = process.env.PN_BOSS_CLI_GRPC_APIKEY ?? '';
if (!grpcHost) {
throw new Error('Missing env variable PN_BOSS_CLI_GRPC_HOST');
}
if (!grpcKey) {
throw new Error('Missing env variable PN_BOSS_CLI_GRPC_APIKEY');
}
console.log(`Connecting to BOSS server at ${grpcHost}`);
const channel = createChannel(grpcHost);
const client: BOSSClient = createClient(BOSSDefinition, channel, {
'*': {
metadata: new Metadata({
'X-API-Key': grpcKey
})
}
});
return {
grpc: client
};
}

View File

@ -1,7 +1,7 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/server.ts'],
entry: ['src/server.ts', 'src/cli/cli.ts'],
splitting: false,
sourcemap: true,
platform: 'node',