@morten-olsen/builder-cli 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.auth-store.d.ts +14 -0
- package/dist/cli.auth-store.d.ts.map +1 -0
- package/dist/cli.auth-store.js +37 -0
- package/dist/cli.auth-store.js.map +1 -0
- package/dist/cli.context.d.ts +11 -0
- package/dist/cli.context.d.ts.map +1 -0
- package/dist/cli.context.js +15 -0
- package/dist/cli.context.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.defaults.d.ts +5 -0
- package/dist/cli.defaults.d.ts.map +1 -0
- package/dist/cli.defaults.js +40 -0
- package/dist/cli.defaults.js.map +1 -0
- package/dist/cli.http.d.ts +9 -0
- package/dist/cli.http.d.ts.map +1 -0
- package/dist/cli.http.js +82 -0
- package/dist/cli.http.js.map +1 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.output.d.ts +12 -0
- package/dist/cli.output.d.ts.map +1 -0
- package/dist/cli.output.js +31 -0
- package/dist/cli.output.js.map +1 -0
- package/dist/cli.prompt.d.ts +4 -0
- package/dist/cli.prompt.d.ts.map +1 -0
- package/dist/cli.prompt.js +64 -0
- package/dist/cli.prompt.js.map +1 -0
- package/dist/commands/commands.admin.d.ts +4 -0
- package/dist/commands/commands.admin.d.ts.map +1 -0
- package/dist/commands/commands.admin.js +184 -0
- package/dist/commands/commands.admin.js.map +1 -0
- package/dist/commands/commands.auth.d.ts +4 -0
- package/dist/commands/commands.auth.d.ts.map +1 -0
- package/dist/commands/commands.auth.js +112 -0
- package/dist/commands/commands.auth.js.map +1 -0
- package/dist/commands/commands.identity.d.ts +4 -0
- package/dist/commands/commands.identity.d.ts.map +1 -0
- package/dist/commands/commands.identity.js +117 -0
- package/dist/commands/commands.identity.js.map +1 -0
- package/dist/commands/commands.repo.d.ts +4 -0
- package/dist/commands/commands.repo.d.ts.map +1 -0
- package/dist/commands/commands.repo.js +184 -0
- package/dist/commands/commands.repo.js.map +1 -0
- package/dist/commands/commands.server.d.ts +4 -0
- package/dist/commands/commands.server.d.ts.map +1 -0
- package/dist/commands/commands.server.js +38 -0
- package/dist/commands/commands.server.js.map +1 -0
- package/dist/commands/commands.session.d.ts +4 -0
- package/dist/commands/commands.session.d.ts.map +1 -0
- package/dist/commands/commands.session.js +296 -0
- package/dist/commands/commands.session.js.map +1 -0
- package/dist/exports.d.ts +8 -0
- package/dist/exports.d.ts.map +1 -0
- package/dist/exports.js +5 -0
- package/dist/exports.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Services } from '@morten-olsen/builder-server';
|
|
2
|
+
type AuthData = {
|
|
3
|
+
token: string;
|
|
4
|
+
userId: string;
|
|
5
|
+
};
|
|
6
|
+
declare const saveAuth: (data: AuthData) => void;
|
|
7
|
+
declare const loadAuth: () => AuthData | null;
|
|
8
|
+
declare const clearAuth: () => void;
|
|
9
|
+
declare const requireAuth: (services: Services) => Promise<{
|
|
10
|
+
userId: string;
|
|
11
|
+
}>;
|
|
12
|
+
export type { AuthData };
|
|
13
|
+
export { saveAuth, loadAuth, clearAuth, requireAuth };
|
|
14
|
+
//# sourceMappingURL=cli.auth-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.auth-store.d.ts","sourceRoot":"","sources":["../src/cli.auth-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAK7D,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,QAAA,MAAM,QAAQ,GAAI,MAAM,QAAQ,KAAG,IAGlC,CAAC;AAEF,QAAA,MAAM,QAAQ,QAAO,QAAQ,GAAG,IAO/B,CAAC;AAEF,QAAA,MAAM,SAAS,QAAO,IAMrB,CAAC;AAEF,QAAA,MAAM,WAAW,GAAU,UAAU,QAAQ,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAUzE,CAAC;AAEF,YAAY,EAAE,QAAQ,EAAE,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { AuthService } from '@morten-olsen/builder-server';
|
|
4
|
+
import { BUILDER_HOME } from './cli.defaults.js';
|
|
5
|
+
const AUTH_FILE = path.join(BUILDER_HOME, 'auth.json');
|
|
6
|
+
const saveAuth = (data) => {
|
|
7
|
+
fs.mkdirSync(BUILDER_HOME, { recursive: true, mode: 0o700 });
|
|
8
|
+
fs.writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
9
|
+
};
|
|
10
|
+
const loadAuth = () => {
|
|
11
|
+
try {
|
|
12
|
+
const raw = fs.readFileSync(AUTH_FILE, 'utf-8');
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const clearAuth = () => {
|
|
20
|
+
try {
|
|
21
|
+
fs.unlinkSync(AUTH_FILE);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// File may not exist, that's fine
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const requireAuth = async (services) => {
|
|
28
|
+
const auth = loadAuth();
|
|
29
|
+
if (!auth) {
|
|
30
|
+
throw new Error('Not logged in. Run `builder auth login` or `builder auth register` first.');
|
|
31
|
+
}
|
|
32
|
+
const authService = services.get(AuthService);
|
|
33
|
+
const payload = await authService.verifyToken(auth.token);
|
|
34
|
+
return { userId: payload.sub };
|
|
35
|
+
};
|
|
36
|
+
export { saveAuth, loadAuth, clearAuth, requireAuth };
|
|
37
|
+
//# sourceMappingURL=cli.auth-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.auth-store.js","sourceRoot":"","sources":["../src/cli.auth-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;AAEvD,MAAM,QAAQ,GAAG,CAAC,IAAc,EAAQ,EAAE;IACxC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,GAAoB,EAAE;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,GAAS,EAAE;IAC3B,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,EAAE,QAAkB,EAA+B,EAAE;IAC5E,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE1D,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;AACjC,CAAC,CAAC;AAGF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Config } from '@morten-olsen/builder-server';
|
|
2
|
+
import { Services } from '@morten-olsen/builder-server';
|
|
3
|
+
type CliContext = {
|
|
4
|
+
services: Services;
|
|
5
|
+
config: Config;
|
|
6
|
+
cleanup: () => Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
declare const createCliContext: () => Promise<CliContext>;
|
|
9
|
+
export type { CliContext };
|
|
10
|
+
export { createCliContext };
|
|
11
|
+
//# sourceMappingURL=cli.context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.context.d.ts","sourceRoot":"","sources":["../src/cli.context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAGL,QAAQ,EAKT,MAAM,8BAA8B,CAAC;AAEtC,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF,QAAA,MAAM,gBAAgB,QAAa,OAAO,CAAC,UAAU,CAepD,CAAC;AAEF,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AgentService, NotificationService, Services, createClaudeAgentProvider, createConfig, createNtfyProvider, destroy, } from '@morten-olsen/builder-server';
|
|
2
|
+
const createCliContext = async () => {
|
|
3
|
+
const config = createConfig();
|
|
4
|
+
const services = new Services(config);
|
|
5
|
+
const agentService = services.get(AgentService);
|
|
6
|
+
agentService.registerProvider(createClaudeAgentProvider(config.agent.apiKey, config.agent.model));
|
|
7
|
+
const notificationService = services.get(NotificationService);
|
|
8
|
+
notificationService.registerProvider(createNtfyProvider());
|
|
9
|
+
const cleanup = async () => {
|
|
10
|
+
await services[destroy]();
|
|
11
|
+
};
|
|
12
|
+
return { services, config, cleanup };
|
|
13
|
+
};
|
|
14
|
+
export { createCliContext };
|
|
15
|
+
//# sourceMappingURL=cli.context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.context.js","sourceRoot":"","sources":["../src/cli.context.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,yBAAyB,EACzB,YAAY,EACZ,kBAAkB,EAClB,OAAO,GACR,MAAM,8BAA8B,CAAC;AAQtC,MAAM,gBAAgB,GAAG,KAAK,IAAyB,EAAE;IACvD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChD,YAAY,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElG,MAAM,mBAAmB,GAAG,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC9D,mBAAmB,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAE3D,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACxC,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACvC,CAAC,CAAC;AAGF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAGA,OAAO,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.defaults.d.ts","sourceRoot":"","sources":["../src/cli.defaults.ts"],"names":[],"mappings":"AAKA,OAAO,eAAe,CAAC;AAEvB,QAAA,MAAM,YAAY,QAAsC,CAAC;AA8BzD,QAAA,MAAM,gBAAgB,QAAO,IAQ5B,CAAC;AAMF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import 'dotenv/config';
|
|
6
|
+
const BUILDER_HOME = path.join(os.homedir(), '.builder');
|
|
7
|
+
const SECRETS_FILE = path.join(BUILDER_HOME, 'secrets.json');
|
|
8
|
+
const loadOrCreateSecrets = () => {
|
|
9
|
+
try {
|
|
10
|
+
const raw = fs.readFileSync(SECRETS_FILE, 'utf-8');
|
|
11
|
+
return JSON.parse(raw);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
const secrets = {
|
|
15
|
+
jwtSecret: randomBytes(32).toString('hex'),
|
|
16
|
+
encryptionKey: randomBytes(32).toString('hex'),
|
|
17
|
+
};
|
|
18
|
+
fs.mkdirSync(BUILDER_HOME, { recursive: true, mode: 0o700 });
|
|
19
|
+
fs.writeFileSync(SECRETS_FILE, JSON.stringify(secrets, null, 2), { mode: 0o600 });
|
|
20
|
+
return secrets;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const setDefaultEnv = (key, value) => {
|
|
24
|
+
if (!process.env[key]) {
|
|
25
|
+
process.env[key] = value;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const applyCliDefaults = () => {
|
|
29
|
+
const secrets = loadOrCreateSecrets();
|
|
30
|
+
setDefaultEnv('DB_PATH', path.join(BUILDER_HOME, 'builder.db'));
|
|
31
|
+
setDefaultEnv('SESSION_DATA_DIR', path.join(BUILDER_HOME, 'data'));
|
|
32
|
+
setDefaultEnv('JWT_SECRET', secrets.jwtSecret);
|
|
33
|
+
setDefaultEnv('ENCRYPTION_KEY', secrets.encryptionKey);
|
|
34
|
+
setDefaultEnv('BUILDER_SERVER_URL', 'http://localhost:4120');
|
|
35
|
+
};
|
|
36
|
+
// Auto-apply at import time — this module MUST be imported before @morten-olsen/builder-server
|
|
37
|
+
// so that env vars are set before convict reads them at schema definition time.
|
|
38
|
+
applyCliDefaults();
|
|
39
|
+
export { BUILDER_HOME, applyCliDefaults };
|
|
40
|
+
//# sourceMappingURL=cli.defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.defaults.js","sourceRoot":"","sources":["../src/cli.defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,eAAe,CAAC;AAEvB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAOzD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAE7D,MAAM,mBAAmB,GAAG,GAAY,EAAE;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,OAAO,GAAY;YACvB,SAAS,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC1C,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;SAC/C,CAAC;QACF,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClF,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,KAAa,EAAQ,EAAE;IACzD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,GAAS,EAAE;IAClC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IAEtC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAChE,aAAa,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACnE,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACvD,aAAa,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,CAAC;AAC/D,CAAC,CAAC;AAEF,+FAA+F;AAC/F,gFAAgF;AAChF,gBAAgB,EAAE,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SessionEvent } from '@morten-olsen/builder-server';
|
|
2
|
+
type HttpClient = {
|
|
3
|
+
post: (path: string, body: unknown) => Promise<unknown>;
|
|
4
|
+
streamSSE: (path: string, onEvent: (event: SessionEvent) => void, until: (event: SessionEvent) => boolean) => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
declare const createHttpClient: (baseUrl: string, token: string) => HttpClient;
|
|
7
|
+
export type { HttpClient };
|
|
8
|
+
export { createHttpClient };
|
|
9
|
+
//# sourceMappingURL=cli.http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.http.d.ts","sourceRoot":"","sources":["../src/cli.http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,SAAS,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,EACtC,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,UA0F1D,CAAC;AAEF,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
package/dist/cli.http.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const createHttpClient = (baseUrl, token) => {
|
|
2
|
+
const post = async (path, body) => {
|
|
3
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
4
|
+
method: 'POST',
|
|
5
|
+
headers: {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
Authorization: `Bearer ${token}`,
|
|
8
|
+
},
|
|
9
|
+
body: JSON.stringify(body),
|
|
10
|
+
});
|
|
11
|
+
if (!response.ok) {
|
|
12
|
+
const text = await response.text();
|
|
13
|
+
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
14
|
+
}
|
|
15
|
+
return response.json();
|
|
16
|
+
};
|
|
17
|
+
const streamSSE = async (path, onEvent, until) => {
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${token}`,
|
|
22
|
+
Accept: 'text/event-stream',
|
|
23
|
+
},
|
|
24
|
+
signal: controller.signal,
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const text = await response.text();
|
|
28
|
+
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
29
|
+
}
|
|
30
|
+
if (!response.body) {
|
|
31
|
+
throw new Error('No response body for SSE stream');
|
|
32
|
+
}
|
|
33
|
+
const reader = response.body.getReader();
|
|
34
|
+
const decoder = new TextDecoder();
|
|
35
|
+
let buffer = '';
|
|
36
|
+
try {
|
|
37
|
+
while (true) {
|
|
38
|
+
const { done, value } = await reader.read();
|
|
39
|
+
if (done)
|
|
40
|
+
break;
|
|
41
|
+
buffer += decoder.decode(value, { stream: true });
|
|
42
|
+
const lines = buffer.split('\n');
|
|
43
|
+
buffer = lines.pop() ?? '';
|
|
44
|
+
let eventType = '';
|
|
45
|
+
let data = '';
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
if (line.startsWith('event: ')) {
|
|
48
|
+
eventType = line.slice(7).trim();
|
|
49
|
+
}
|
|
50
|
+
else if (line.startsWith('data: ')) {
|
|
51
|
+
data = line.slice(6).trim();
|
|
52
|
+
}
|
|
53
|
+
else if (line === '' && eventType && data) {
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(data);
|
|
56
|
+
const event = { type: eventType, data: parsed };
|
|
57
|
+
onEvent(event);
|
|
58
|
+
if (until(event)) {
|
|
59
|
+
controller.abort();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Skip malformed events
|
|
65
|
+
}
|
|
66
|
+
eventType = '';
|
|
67
|
+
data = '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
return { post, streamSSE };
|
|
80
|
+
};
|
|
81
|
+
export { createHttpClient };
|
|
82
|
+
//# sourceMappingURL=cli.http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.http.js","sourceRoot":"","sources":["../src/cli.http.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Must be first import — sets env defaults before server module's convict schema reads them.
|
|
3
|
+
import './cli.defaults.js';
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { registerAdminCommands } from './commands/commands.admin.js';
|
|
6
|
+
import { registerAuthCommands } from './commands/commands.auth.js';
|
|
7
|
+
import { registerIdentityCommands } from './commands/commands.identity.js';
|
|
8
|
+
import { registerRepoCommands } from './commands/commands.repo.js';
|
|
9
|
+
import { registerServerCommands } from './commands/commands.server.js';
|
|
10
|
+
import { registerSessionCommands } from './commands/commands.session.js';
|
|
11
|
+
import { printError } from './cli.output.js';
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program
|
|
14
|
+
.name('builder')
|
|
15
|
+
.description('CLI for the coding agent orchestrator')
|
|
16
|
+
.version('1.0.0');
|
|
17
|
+
registerServerCommands(program);
|
|
18
|
+
registerAuthCommands(program);
|
|
19
|
+
registerIdentityCommands(program);
|
|
20
|
+
registerRepoCommands(program);
|
|
21
|
+
registerSessionCommands(program);
|
|
22
|
+
registerAdminCommands(program);
|
|
23
|
+
program.parseAsync().catch((error) => {
|
|
24
|
+
printError(error instanceof Error ? error.message : String(error));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,6FAA6F;AAC7F,OAAO,mBAAmB,CAAC;AAE3B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC5C,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
type Column = {
|
|
3
|
+
header: string;
|
|
4
|
+
key: string;
|
|
5
|
+
};
|
|
6
|
+
declare const printTable: (rows: Record<string, unknown>[], columns: Column[]) => void;
|
|
7
|
+
declare const printJson: (data: unknown) => void;
|
|
8
|
+
declare const printError: (message: string) => void;
|
|
9
|
+
declare const isJson: (cmd: Command) => boolean;
|
|
10
|
+
export type { Column };
|
|
11
|
+
export { printTable, printJson, printError, isJson };
|
|
12
|
+
//# sourceMappingURL=cli.output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.output.d.ts","sourceRoot":"","sources":["../src/cli.output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,KAAK,MAAM,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,QAAA,MAAM,UAAU,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,KAAG,IAsBxE,CAAC;AAEF,QAAA,MAAM,SAAS,GAAI,MAAM,OAAO,KAAG,IAElC,CAAC;AAEF,QAAA,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAErC,CAAC;AAEF,QAAA,MAAM,MAAM,GAAI,KAAK,OAAO,KAAG,OAE9B,CAAC;AAEF,YAAY,EAAE,MAAM,EAAE,CAAC;AACvB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const printTable = (rows, columns) => {
|
|
2
|
+
if (rows.length === 0) {
|
|
3
|
+
console.log('No results.');
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
const widths = columns.map((col) => {
|
|
7
|
+
const maxValLen = rows.reduce((max, row) => {
|
|
8
|
+
const val = String(row[col.key] ?? '');
|
|
9
|
+
return Math.max(max, val.length);
|
|
10
|
+
}, 0);
|
|
11
|
+
return Math.max(col.header.length, maxValLen);
|
|
12
|
+
});
|
|
13
|
+
const header = columns.map((col, i) => col.header.padEnd(widths[i])).join(' ');
|
|
14
|
+
console.log(header);
|
|
15
|
+
console.log(columns.map((_, i) => '-'.repeat(widths[i])).join(' '));
|
|
16
|
+
for (const row of rows) {
|
|
17
|
+
const line = columns.map((col, i) => String(row[col.key] ?? '').padEnd(widths[i])).join(' ');
|
|
18
|
+
console.log(line);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const printJson = (data) => {
|
|
22
|
+
console.log(JSON.stringify(data, null, 2));
|
|
23
|
+
};
|
|
24
|
+
const printError = (message) => {
|
|
25
|
+
console.error(`Error: ${message}`);
|
|
26
|
+
};
|
|
27
|
+
const isJson = (cmd) => {
|
|
28
|
+
return cmd.optsWithGlobals().json === true;
|
|
29
|
+
};
|
|
30
|
+
export { printTable, printJson, printError, isJson };
|
|
31
|
+
//# sourceMappingURL=cli.output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.output.js","sourceRoot":"","sources":["../src/cli.output.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,GAAG,CAAC,IAA+B,EAAE,OAAiB,EAAQ,EAAE;IAC9E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACzC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,EAAE,CAAC,CAAC,CAAC;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAErE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,IAAa,EAAQ,EAAE;IACxC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe,EAAQ,EAAE;IAC3C,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,GAAY,EAAW,EAAE;IACvC,OAAO,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;AAC7C,CAAC,CAAC;AAGF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.prompt.d.ts","sourceRoot":"","sources":["../src/cli.prompt.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAwDvD,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAOxE,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as readline from 'node:readline';
|
|
2
|
+
const promptPassword = (message) => {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
process.stdout.write(message);
|
|
5
|
+
if (!process.stdin.isTTY) {
|
|
6
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
7
|
+
rl.question('', (answer) => {
|
|
8
|
+
rl.close();
|
|
9
|
+
resolve(answer);
|
|
10
|
+
});
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let input = '';
|
|
14
|
+
process.stdin.setRawMode(true);
|
|
15
|
+
process.stdin.resume();
|
|
16
|
+
process.stdin.setEncoding('utf8');
|
|
17
|
+
const onData = (char) => {
|
|
18
|
+
switch (char) {
|
|
19
|
+
case '\n':
|
|
20
|
+
case '\r':
|
|
21
|
+
case '\u0004': {
|
|
22
|
+
process.stdin.setRawMode(false);
|
|
23
|
+
process.stdin.pause();
|
|
24
|
+
process.stdin.removeListener('data', onData);
|
|
25
|
+
process.stdout.write('\n');
|
|
26
|
+
resolve(input);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case '\u0003': {
|
|
30
|
+
process.stdin.setRawMode(false);
|
|
31
|
+
process.stdin.pause();
|
|
32
|
+
process.stdin.removeListener('data', onData);
|
|
33
|
+
process.stdout.write('\n');
|
|
34
|
+
reject(new Error('User cancelled'));
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case '\u007f':
|
|
38
|
+
case '\b': {
|
|
39
|
+
if (input.length > 0) {
|
|
40
|
+
input = input.slice(0, -1);
|
|
41
|
+
process.stdout.write('\b \b');
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
default: {
|
|
46
|
+
input += char;
|
|
47
|
+
process.stdout.write('*');
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
process.stdin.on('data', onData);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const promptPasswordWithConfirm = async (message) => {
|
|
56
|
+
const password = await promptPassword(message);
|
|
57
|
+
const confirm = await promptPassword('Confirm password: ');
|
|
58
|
+
if (password !== confirm) {
|
|
59
|
+
throw new Error('Passwords do not match');
|
|
60
|
+
}
|
|
61
|
+
return password;
|
|
62
|
+
};
|
|
63
|
+
export { promptPassword, promptPasswordWithConfirm };
|
|
64
|
+
//# sourceMappingURL=cli.prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.prompt.js","sourceRoot":"","sources":["../src/cli.prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.admin.d.ts","sourceRoot":"","sources":["../../src/commands/commands.admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAmLjD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { AuthService, DatabaseService, IdentityService, RepoService, SessionService, } from '@morten-olsen/builder-server';
|
|
2
|
+
import { createCliContext } from '../cli.context.js';
|
|
3
|
+
import { isJson, printJson, printTable } from '../cli.output.js';
|
|
4
|
+
import { promptPasswordWithConfirm } from '../cli.prompt.js';
|
|
5
|
+
const registerAdminCommands = (program) => {
|
|
6
|
+
const admin = program.command('admin').description('Admin commands (all users)');
|
|
7
|
+
admin
|
|
8
|
+
.command('users')
|
|
9
|
+
.description('List all users')
|
|
10
|
+
.option('--json', 'Output as JSON')
|
|
11
|
+
.action(async function () {
|
|
12
|
+
const { services, cleanup } = await createCliContext();
|
|
13
|
+
try {
|
|
14
|
+
const authService = services.get(AuthService);
|
|
15
|
+
const users = await authService.listUsers();
|
|
16
|
+
if (isJson(this)) {
|
|
17
|
+
printJson(users);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
printTable(users, [
|
|
21
|
+
{ header: 'ID', key: 'id' },
|
|
22
|
+
{ header: 'Created', key: 'createdAt' },
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await cleanup();
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
admin
|
|
31
|
+
.command('repos')
|
|
32
|
+
.description('List all repos')
|
|
33
|
+
.option('--user <id>', 'Filter by user ID')
|
|
34
|
+
.option('--json', 'Output as JSON')
|
|
35
|
+
.action(async function () {
|
|
36
|
+
const opts = this.opts();
|
|
37
|
+
const { services, cleanup } = await createCliContext();
|
|
38
|
+
try {
|
|
39
|
+
const repoService = services.get(RepoService);
|
|
40
|
+
const repos = await repoService.listAll(opts.user);
|
|
41
|
+
if (isJson(this)) {
|
|
42
|
+
printJson(repos);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
printTable(repos, [
|
|
46
|
+
{ header: 'ID', key: 'id' },
|
|
47
|
+
{ header: 'User', key: 'userId' },
|
|
48
|
+
{ header: 'Name', key: 'name' },
|
|
49
|
+
{ header: 'URL', key: 'repoUrl' },
|
|
50
|
+
{ header: 'Branch', key: 'defaultBranch' },
|
|
51
|
+
{ header: 'Created', key: 'createdAt' },
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
await cleanup();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
admin
|
|
60
|
+
.command('identities')
|
|
61
|
+
.description('List all identities')
|
|
62
|
+
.option('--user <id>', 'Filter by user ID')
|
|
63
|
+
.option('--json', 'Output as JSON')
|
|
64
|
+
.action(async function () {
|
|
65
|
+
const opts = this.opts();
|
|
66
|
+
const { services, cleanup } = await createCliContext();
|
|
67
|
+
try {
|
|
68
|
+
const identityService = services.get(IdentityService);
|
|
69
|
+
const identities = await identityService.listAll(opts.user);
|
|
70
|
+
if (isJson(this)) {
|
|
71
|
+
printJson(identities);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
printTable(identities, [
|
|
75
|
+
{ header: 'ID', key: 'id' },
|
|
76
|
+
{ header: 'User', key: 'userId' },
|
|
77
|
+
{ header: 'Name', key: 'name' },
|
|
78
|
+
{ header: 'Git Name', key: 'gitAuthorName' },
|
|
79
|
+
{ header: 'Git Email', key: 'gitAuthorEmail' },
|
|
80
|
+
{ header: 'Created', key: 'createdAt' },
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
await cleanup();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
admin
|
|
89
|
+
.command('sessions')
|
|
90
|
+
.description('List all sessions')
|
|
91
|
+
.option('--user <id>', 'Filter by user ID')
|
|
92
|
+
.option('--json', 'Output as JSON')
|
|
93
|
+
.action(async function () {
|
|
94
|
+
const opts = this.opts();
|
|
95
|
+
const { services, cleanup } = await createCliContext();
|
|
96
|
+
try {
|
|
97
|
+
const sessionService = services.get(SessionService);
|
|
98
|
+
const sessions = await sessionService.listAll(opts.user);
|
|
99
|
+
if (isJson(this)) {
|
|
100
|
+
printJson(sessions);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
printTable(sessions, [
|
|
104
|
+
{ header: 'ID', key: 'id' },
|
|
105
|
+
{ header: 'User', key: 'userId' },
|
|
106
|
+
{ header: 'Repo', key: 'repoId' },
|
|
107
|
+
{ header: 'Status', key: 'status' },
|
|
108
|
+
{ header: 'Branch', key: 'branch' },
|
|
109
|
+
{ header: 'Created', key: 'createdAt' },
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await cleanup();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
admin
|
|
118
|
+
.command('reset-password')
|
|
119
|
+
.description('Reset a user password')
|
|
120
|
+
.requiredOption('--user <userId>', 'User ID')
|
|
121
|
+
.option('--password <password>', 'New password (omit to enter securely)')
|
|
122
|
+
.option('--json', 'Output as JSON')
|
|
123
|
+
.action(async function () {
|
|
124
|
+
const opts = this.opts();
|
|
125
|
+
const newPassword = opts.password ?? (await promptPasswordWithConfirm('New password: '));
|
|
126
|
+
const { services, cleanup } = await createCliContext();
|
|
127
|
+
try {
|
|
128
|
+
const authService = services.get(AuthService);
|
|
129
|
+
await authService.adminResetPassword({ userId: opts.user, newPassword });
|
|
130
|
+
if (isJson(this)) {
|
|
131
|
+
printJson({ success: true });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log('Password reset successfully.');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
await cleanup();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
admin
|
|
142
|
+
.command('set-worktree-base')
|
|
143
|
+
.description('Set a custom worktree base directory for a user')
|
|
144
|
+
.requiredOption('--user <id>', 'User ID')
|
|
145
|
+
.requiredOption('--path <path>', 'Worktree base directory (use "default" to clear)')
|
|
146
|
+
.option('--json', 'Output as JSON')
|
|
147
|
+
.action(async function () {
|
|
148
|
+
const opts = this.opts();
|
|
149
|
+
const { services, cleanup } = await createCliContext();
|
|
150
|
+
try {
|
|
151
|
+
const worktreeBase = opts.path === 'default' ? null : opts.path;
|
|
152
|
+
const db = await services.get(DatabaseService).getInstance();
|
|
153
|
+
const user = await db
|
|
154
|
+
.selectFrom('users')
|
|
155
|
+
.select('id')
|
|
156
|
+
.where('id', '=', opts.user)
|
|
157
|
+
.executeTakeFirst();
|
|
158
|
+
if (!user) {
|
|
159
|
+
throw new Error(`User "${opts.user}" not found`);
|
|
160
|
+
}
|
|
161
|
+
await db
|
|
162
|
+
.updateTable('users')
|
|
163
|
+
.set({ worktree_base: worktreeBase, updated_at: new Date().toISOString() })
|
|
164
|
+
.where('id', '=', opts.user)
|
|
165
|
+
.execute();
|
|
166
|
+
if (isJson(this)) {
|
|
167
|
+
printJson({ success: true, worktreeBase });
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
if (worktreeBase) {
|
|
171
|
+
console.log(`Worktree base set to: ${worktreeBase}`);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.log('Worktree base reset to default.');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
await cleanup();
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
export { registerAdminCommands };
|
|
184
|
+
//# sourceMappingURL=commands.admin.js.map
|