@skhema/cli 0.4.3 → 0.4.4

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.
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Document commands — workspace-authored narrative artifacts (board updates,
4
+ * team briefs, decision briefs, custom docs). All are workspace-scoped via
5
+ * `--workspace` (falling back to the default set by `skhema workspace use`).
6
+ * The routes carry the workspace id in the path, so — unlike `workspace list`
7
+ * — no organizationId is forwarded; the gateway authorizes via workspace access.
8
+ */
9
+ export declare function registerDocumentCommands(program: Command): void;
10
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/commands/document.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAqBnC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgK/D"}
@@ -0,0 +1,122 @@
1
+ import chalk from 'chalk';
2
+ import { resolveClient } from '../lib/api/client.js';
3
+ import { asRecord, buildBody, coerceList, readPayloadFile, resolveWorkspaceId, } from '../lib/api/command-helpers.js';
4
+ import { runCommand, UsageError } from '../lib/api/run-command.js';
5
+ import { getGlobalOptions, log, logHeader, logTable } from '../lib/output.js';
6
+ /** Print a single document as a label block (human output only). */
7
+ function printDocument(document) {
8
+ const d = asRecord(document);
9
+ logHeader(String(d.title ?? d.id ?? 'Document'));
10
+ log(` Id: ${chalk.cyan(String(d.id ?? '—'))}`);
11
+ if (d.docType)
12
+ log(` Type: ${String(d.docType)}`);
13
+ if (d.updatedAt)
14
+ log(` Updated: ${String(d.updatedAt)}`);
15
+ }
16
+ /**
17
+ * Document commands — workspace-authored narrative artifacts (board updates,
18
+ * team briefs, decision briefs, custom docs). All are workspace-scoped via
19
+ * `--workspace` (falling back to the default set by `skhema workspace use`).
20
+ * The routes carry the workspace id in the path, so — unlike `workspace list`
21
+ * — no organizationId is forwarded; the gateway authorizes via workspace access.
22
+ */
23
+ export function registerDocumentCommands(program) {
24
+ const document = program.command('document').description('Document commands');
25
+ const withWorkspace = (cmd) => cmd.option('--workspace <id>', 'Workspace id (defaults to `skhema workspace use`)');
26
+ withWorkspace(document.command('list').description('List documents')).action(async (options) => {
27
+ await runCommand('document list', async () => {
28
+ const workspaceId = resolveWorkspaceId(options.workspace);
29
+ const { client } = await resolveClient();
30
+ const data = await client.documents.list(workspaceId);
31
+ const rows = coerceList(data, 'documents');
32
+ if (!getGlobalOptions().json) {
33
+ logHeader(`Documents (${rows.length})`);
34
+ if (rows.length === 0)
35
+ log(chalk.dim(' No documents.'));
36
+ else
37
+ logTable(['Title', 'Type', 'Updated', 'Id'], rows.map((r) => {
38
+ const d = asRecord(r);
39
+ return [
40
+ String(d.title ?? '—'),
41
+ String(d.docType ?? '—'),
42
+ String(d.updatedAt ?? '—'),
43
+ String(d.id ?? '—'),
44
+ ];
45
+ }));
46
+ }
47
+ return data;
48
+ });
49
+ });
50
+ withWorkspace(document.command('get <document-id>').description('Get a document by id')).action(async (documentId, options) => {
51
+ await runCommand('document get', async () => {
52
+ const workspaceId = resolveWorkspaceId(options.workspace);
53
+ const { client } = await resolveClient();
54
+ const data = await client.documents.get(workspaceId, documentId);
55
+ if (!getGlobalOptions().json)
56
+ printDocument(asRecord(data).document ?? data);
57
+ return data;
58
+ });
59
+ });
60
+ withWorkspace(document
61
+ .command('create')
62
+ .description('Create a document')
63
+ .option('--title <title>', 'Document title')
64
+ .option('--doc-type <type>', 'Document type (board_update | team_brief | decision_brief | custom)')
65
+ .option('--content <content>', 'Document content')
66
+ .option('--file <path>', 'JSON payload file for the full body ("-" for stdin)')).action(async (options) => {
67
+ await runCommand('document create', async () => {
68
+ const workspaceId = resolveWorkspaceId(options.workspace);
69
+ const body = buildBody(readPayloadFile(options.file), {
70
+ title: options.title,
71
+ docType: options.docType,
72
+ content: options.content,
73
+ });
74
+ if (Object.keys(body).length === 0) {
75
+ throw new UsageError('Nothing to create. Pass document fields as flags or a --file payload.');
76
+ }
77
+ const { client } = await resolveClient();
78
+ const data = await client.documents.create(workspaceId, body);
79
+ if (!getGlobalOptions().json) {
80
+ log(chalk.green('Document created.'));
81
+ printDocument(asRecord(data).document ?? data);
82
+ }
83
+ return data;
84
+ });
85
+ });
86
+ withWorkspace(document
87
+ .command('update <document-id>')
88
+ .description('Update a document')
89
+ .option('--title <title>', 'Document title')
90
+ .option('--doc-type <type>', 'Document type (board_update | team_brief | decision_brief | custom)')
91
+ .option('--content <content>', 'Document content')
92
+ .option('--file <path>', 'JSON payload file for the full body ("-" for stdin)')).action(async (documentId, options) => {
93
+ await runCommand('document update', async () => {
94
+ const workspaceId = resolveWorkspaceId(options.workspace);
95
+ const body = buildBody(readPayloadFile(options.file), {
96
+ title: options.title,
97
+ docType: options.docType,
98
+ content: options.content,
99
+ });
100
+ if (Object.keys(body).length === 0) {
101
+ throw new UsageError('Nothing to update. Pass document fields as flags or a --file payload.');
102
+ }
103
+ const { client } = await resolveClient();
104
+ const data = await client.documents.update(workspaceId, documentId, body);
105
+ if (!getGlobalOptions().json) {
106
+ log(chalk.green('Document updated.'));
107
+ printDocument(asRecord(data).document ?? data);
108
+ }
109
+ return data;
110
+ });
111
+ });
112
+ withWorkspace(document.command('delete <document-id>').description('Delete a document')).action(async (documentId, options) => {
113
+ await runCommand('document delete', async () => {
114
+ const workspaceId = resolveWorkspaceId(options.workspace);
115
+ const { client } = await resolveClient();
116
+ const data = await client.documents.delete(workspaceId, documentId);
117
+ if (!getGlobalOptions().json)
118
+ log(chalk.green(`Deleted document ${documentId}.`));
119
+ return data;
120
+ });
121
+ });
122
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"command-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/command-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAKzC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAsB1E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,WAAW,CAMb;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIhE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAQlE"}
1
+ {"version":3,"file":"command-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/command-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAKzC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAuB1E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,WAAW,CAMb;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIhE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAQlE"}
@@ -29,7 +29,8 @@ export function readPayloadFile(filePath) {
29
29
  throw new UsageError(`Could not read payload file "${filePath}": ${err instanceof Error ? err.message : String(err)}`);
30
30
  }
31
31
  try {
32
- const parsed = JSON.parse(raw);
32
+ // Strip a leading UTF-8 BOM so a byte-identical-looking file parses.
33
+ const parsed = JSON.parse(raw.replace(/^\uFEFF/, ''));
33
34
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
34
35
  throw new Error('expected a JSON object');
35
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"passthrough.d.ts","sourceRoot":"","sources":["../../../src/lib/api/passthrough.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAW7C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAQvD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAyBrE;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,EAAE,EAAE;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACjC,GACA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CA+B9C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,GACxB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CASzB"}
1
+ {"version":3,"file":"passthrough.d.ts","sourceRoot":"","sources":["../../../src/lib/api/passthrough.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAW7C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAQvD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAyBrE;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,EAAE,EAAE;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACjC,GACA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CA2C9C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,GACxB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CASzB"}
@@ -79,10 +79,19 @@ export async function resolveDataBody(raw, io) {
79
79
  }
80
80
  let parsed;
81
81
  try {
82
- parsed = JSON.parse(text);
82
+ // Strip a leading UTF-8 BOM (editors and some `echo`/redirect toolchains
83
+ // prepend one); JSON.parse chokes on it, which surfaced as the opaque
84
+ // "--data is not valid JSON" even for a well-formed @file. Mirrors curl.
85
+ parsed = JSON.parse(text.replace(/^\uFEFF/, ''));
83
86
  }
84
- catch {
85
- throw new UsageError('--data is not valid JSON.');
87
+ catch (err) {
88
+ // Name the source so a failed @file is not mistaken for the literal form.
89
+ const label = raw === '-'
90
+ ? 'from stdin'
91
+ : raw.startsWith('@')
92
+ ? `file "${raw.slice(1)}"`
93
+ : 'value';
94
+ throw new UsageError(`--data ${label} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
86
95
  }
87
96
  if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
88
97
  throw new UsageError('--data must be a JSON object.');
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/lib/api/payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAI9C,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAatD;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAczD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,WAAW,CAad"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/lib/api/payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAI9C,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAatD;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAezD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,WAAW,CAad"}
@@ -22,7 +22,8 @@ export function parseJsonFile(source) {
22
22
  const raw = readFileOrStdin(source);
23
23
  let parsed;
24
24
  try {
25
- parsed = JSON.parse(raw);
25
+ // Strip a leading UTF-8 BOM so a byte-identical-looking file parses.
26
+ parsed = JSON.parse(raw.replace(/^\uFEFF/, ''));
26
27
  }
27
28
  catch {
28
29
  throw new UsageError(`Payload in ${source === '-' ? 'stdin' : source} is not valid JSON.`);
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAmBnC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA+CrD"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoBnC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgDrD"}
package/dist/program.js CHANGED
@@ -4,6 +4,7 @@ import { registerApiCommands } from './commands/api.js';
4
4
  import { registerAuthCommands } from './commands/auth.js';
5
5
  import { registerComponentCommands } from './commands/component.js';
6
6
  import { registerContributeCommands } from './commands/contribute.js';
7
+ import { registerDocumentCommands } from './commands/document.js';
7
8
  import { registerElementCommands } from './commands/element.js';
8
9
  import { registerWorkspaceExportCommand } from './commands/export.js';
9
10
  import { registerInitCommand } from './commands/init.js';
@@ -53,6 +54,7 @@ export function buildProgram(version) {
53
54
  registerWorkspaceExportCommand(program);
54
55
  registerComponentCommands(program);
55
56
  registerStrategyCommands(program);
57
+ registerDocumentCommands(program);
56
58
  registerResourceCommands(program);
57
59
  registerWebhookCommands(program);
58
60
  registerAgentCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skhema/cli",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Skhema CLI - Authentication and AI skills management for agent platforms",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "dependencies": {
44
44
  "@skhema/agent-sdk": "0.1.4",
45
45
  "@skhema/method": "0.3.0",
46
- "@skhema/sdk": "0.2.1",
46
+ "@skhema/sdk": "0.2.2",
47
47
  "chalk": "^5.3.0",
48
48
  "commander": "^12.0.0",
49
49
  "ora": "^8.0.0"