@stndrds/cli 1.0.0-alpha.2 → 1.0.0-alpha.3

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.
Files changed (2) hide show
  1. package/dist/bin.mjs +327 -132
  2. package/package.json +1 -1
package/dist/bin.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/bin.ts
4
- import chalk3 from "chalk";
3
+ // src/program.ts
4
+ import chalk5 from "chalk";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/client.ts
@@ -13,7 +13,9 @@ var ApiClientError = class extends Error {
13
13
  }
14
14
  };
15
15
  function buildUrl(base, path, params) {
16
- const url = new URL(path, base);
16
+ const normalizedBase = base.endsWith("/") ? base : `${base}/`;
17
+ const normalizedPath = path.replace(/^\/+/, "");
18
+ const url = new URL(normalizedPath, normalizedBase);
17
19
  if (params) {
18
20
  for (const [key, value] of Object.entries(params)) {
19
21
  if (value !== void 0 && value !== null) {
@@ -75,10 +77,48 @@ function createClient(config) {
75
77
  }
76
78
 
77
79
  // src/commands/auth.ts
78
- import chalk2 from "chalk";
80
+ import chalk from "chalk";
81
+
82
+ // src/commands/common.ts
83
+ function getGlobalOptions(cmd) {
84
+ return cmd.optsWithGlobals();
85
+ }
86
+ function getFormat(cmd) {
87
+ return getGlobalOptions(cmd).format;
88
+ }
89
+ function getClientFromCommand(cmd) {
90
+ const root = getGlobalOptions(cmd);
91
+ if (!(root.apiUrl && root.apiKey)) {
92
+ throw new Error('No Standards instance configured. Run "standards login" or pass --api-key.');
93
+ }
94
+ return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey });
95
+ }
96
+
97
+ // src/commands/auth.ts
98
+ function registerAuthCommand(program) {
99
+ const auth = program.command("auth").description("Inspect CLI authentication");
100
+ auth.command("whoami").description("Show current configuration and validate API key").action(async (_opts, cmd) => {
101
+ const root = getGlobalOptions(cmd);
102
+ const client = getClientFromCommand(cmd);
103
+ const write = (msg) => process.stdout.write(`${msg}
104
+ `);
105
+ write(chalk.bold("Standards CLI Configuration"));
106
+ write(` API URL: ${root.apiUrl}`);
107
+ write(` API Key: ${root.apiKey ? `${root.apiKey.slice(0, 8)}...` : chalk.red("not set")}`);
108
+ write("");
109
+ const keys = await client.get("/api-keys");
110
+ write(chalk.green("\u2713 API key is valid"));
111
+ if (Array.isArray(keys) && keys.length > 0) {
112
+ const activeKeys = keys.filter(
113
+ (key) => typeof key === "object" && key !== null && !("revokedAt" in key && key.revokedAt)
114
+ );
115
+ write(` Active keys: ${activeKeys.length}`);
116
+ }
117
+ });
118
+ }
79
119
 
80
120
  // src/output.ts
81
- import chalk from "chalk";
121
+ import chalk2 from "chalk";
82
122
  import Table from "cli-table3";
83
123
  var MAX_CELL_WIDTH = 50;
84
124
  function truncate(value, maxLength) {
@@ -107,7 +147,7 @@ function formatTable(items) {
107
147
  if (items.length === 0) return "No results.";
108
148
  const headers = Object.keys(items[0]);
109
149
  const table = new Table({
110
- head: headers.map((h) => chalk.bold(h)),
150
+ head: headers.map((h) => chalk2.bold(h)),
111
151
  style: { head: [], border: [] }
112
152
  });
113
153
  for (const item of items) {
@@ -137,224 +177,379 @@ function formatOutput(data, format) {
137
177
  `);
138
178
  }
139
179
 
140
- // src/commands/auth.ts
141
- function getClientFromCommand(cmd) {
142
- const root = cmd.optsWithGlobals();
143
- return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey });
144
- }
145
- function getFormat(cmd) {
146
- return cmd.optsWithGlobals().format;
147
- }
148
- function registerAuthCommand(program2) {
149
- const auth = program2.command("auth").description("Manage authentication and API keys");
150
- auth.command("whoami").description("Show current configuration and validate API key").action(async (_opts, cmd) => {
151
- const root = cmd.optsWithGlobals();
152
- const client = getClientFromCommand(cmd);
153
- const write = (msg) => process.stdout.write(`${msg}
154
- `);
155
- write(chalk2.bold("Standards CLI Configuration"));
156
- write(` API URL: ${root.apiUrl}`);
157
- write(` API Key: ${root.apiKey ? `${root.apiKey.slice(0, 8)}...` : chalk2.red("not set")}`);
158
- write("");
159
- const keys = await client.get("/api-keys");
160
- write(chalk2.green("\u2713 API key is valid"));
161
- if (Array.isArray(keys) && keys.length > 0) {
162
- write(` Active keys: ${keys.length}`);
163
- }
164
- });
165
- auth.command("create-key").description("Create a new API key").requiredOption("--name <name>", "name for the API key").option("--expires <date>", "expiration date (ISO 8601)").action(async (opts, cmd) => {
166
- const client = getClientFromCommand(cmd);
167
- const body = {
168
- name: opts.name,
169
- permissions: []
170
- };
171
- if (opts.expires) body.expiresAt = opts.expires;
172
- const result = await client.post("/api-keys", body);
173
- formatOutput(result, getFormat(cmd));
174
- });
175
- }
176
-
177
180
  // src/commands/documents.ts
178
- function getClientFromCommand2(cmd) {
179
- const root = cmd.optsWithGlobals();
180
- return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey });
181
- }
182
- function getFormat2(cmd) {
183
- return cmd.optsWithGlobals().format;
184
- }
185
- function registerDocumentsCommand(program2) {
186
- const documents = program2.command("documents").description("Manage documents");
181
+ function registerDocumentsCommand(program) {
182
+ const documents = program.command("documents").description("Manage documents");
187
183
  documents.command("list").description("List documents").option("--status <status>", "filter by processing status").option("--limit <n>", "max documents to return").option("--offset <n>", "number of documents to skip").action(async (opts, cmd) => {
188
- const client = getClientFromCommand2(cmd);
184
+ const client = getClientFromCommand(cmd);
189
185
  const params = {};
190
186
  if (opts.status) params.processingStatus = opts.status;
191
187
  if (opts.limit) params.limit = opts.limit;
192
188
  if (opts.offset) params.offset = opts.offset;
193
189
  const result = await client.get("/documents", params);
194
- formatOutput(result, getFormat2(cmd));
190
+ formatOutput(result, getFormat(cmd));
195
191
  });
196
192
  documents.command("get").description("Get a document by ID").argument("<id>", "document ID").action(async (id, _opts, cmd) => {
197
- const client = getClientFromCommand2(cmd);
193
+ const client = getClientFromCommand(cmd);
198
194
  const result = await client.get(`/documents/${id}`);
199
- formatOutput(result, getFormat2(cmd));
195
+ formatOutput(result, getFormat(cmd));
200
196
  });
201
197
  documents.command("create").description("Create a new document").requiredOption("--title <title>", "document title").option("--values <json>", "document values as JSON string").action(async (opts, cmd) => {
202
- const client = getClientFromCommand2(cmd);
198
+ const client = getClientFromCommand(cmd);
203
199
  const body = { title: opts.title };
204
200
  if (opts.values) body.values = JSON.parse(opts.values);
205
201
  const result = await client.post("/documents", body);
206
- formatOutput(result, getFormat2(cmd));
202
+ formatOutput(result, getFormat(cmd));
207
203
  });
208
204
  documents.command("update").description("Update a document").argument("<id>", "document ID").option("--title <title>", "new title").option("--values <json>", "new values as JSON string").action(async (id, opts, cmd) => {
209
- const client = getClientFromCommand2(cmd);
205
+ const client = getClientFromCommand(cmd);
210
206
  const body = {};
211
207
  if (opts.title) body.title = opts.title;
212
208
  if (opts.values) body.values = JSON.parse(opts.values);
213
209
  const result = await client.patch(`/documents/${id}`, body);
214
- formatOutput(result, getFormat2(cmd));
210
+ formatOutput(result, getFormat(cmd));
215
211
  });
216
212
  documents.command("delete").description("Delete a document").argument("<id>", "document ID").action(async (id, _opts, cmd) => {
217
- const client = getClientFromCommand2(cmd);
213
+ const client = getClientFromCommand(cmd);
218
214
  await client.delete(`/documents/${id}`);
219
215
  process.stdout.write(`Document ${id} deleted.
220
216
  `);
221
217
  });
222
218
  documents.command("preview").description("Get preview file for a document").argument("<id>", "document ID").action(async (id, _opts, cmd) => {
223
- const client = getClientFromCommand2(cmd);
219
+ const client = getClientFromCommand(cmd);
224
220
  const result = await client.get(`/documents/${id}/preview`);
225
- formatOutput(result, getFormat2(cmd));
221
+ formatOutput(result, getFormat(cmd));
226
222
  });
227
223
  documents.command("slots").description("List slots for a document").argument("<id>", "document ID").action(async (id, _opts, cmd) => {
228
- const client = getClientFromCommand2(cmd);
224
+ const client = getClientFromCommand(cmd);
229
225
  const result = await client.get(`/documents/${id}/slots`);
230
- formatOutput(result, getFormat2(cmd));
226
+ formatOutput(result, getFormat(cmd));
231
227
  });
232
228
  documents.command("add-slot").description("Add a file slot to a document").argument("<id>", "document ID").requiredOption("--slot-name <name>", "slot name").requiredOption("--file-id <fileId>", "file ID").action(async (id, opts, cmd) => {
233
- const client = getClientFromCommand2(cmd);
229
+ const client = getClientFromCommand(cmd);
234
230
  const result = await client.post(`/documents/${id}/slots`, {
235
231
  slotName: opts.slotName,
236
232
  fileId: opts.fileId
237
233
  });
238
- formatOutput(result, getFormat2(cmd));
234
+ formatOutput(result, getFormat(cmd));
239
235
  });
240
236
  documents.command("remove-slot").description("Remove a slot from a document").argument("<id>", "document ID").argument("<slotId>", "slot ID").action(async (id, slotId, _opts, cmd) => {
241
- const client = getClientFromCommand2(cmd);
237
+ const client = getClientFromCommand(cmd);
242
238
  await client.delete(`/documents/${id}/slots/${slotId}`);
243
239
  process.stdout.write(`Slot ${slotId} removed.
244
240
  `);
245
241
  });
246
242
  }
247
243
 
248
- // src/commands/records.ts
249
- function getClientFromCommand3(cmd) {
250
- const root = cmd.optsWithGlobals();
251
- return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey });
252
- }
253
- function getFormat3(cmd) {
254
- return cmd.optsWithGlobals().format;
244
+ // src/commands/keys.ts
245
+ import chalk3 from "chalk";
246
+ function registerKeysCommand(program) {
247
+ const keys = program.command("keys").description("Manage Standards API keys");
248
+ keys.command("list").description("List API keys").action(async (_opts, cmd) => {
249
+ const client = getClientFromCommand(cmd);
250
+ const result = await client.get("/api-keys");
251
+ formatOutput(result, getFormat(cmd));
252
+ });
253
+ keys.command("create").description("Create a new API key").requiredOption("--name <name>", "name for the API key").option("--expires <date>", "expiration date (ISO 8601)").option("--yes", "create without confirmation").action(async (opts, cmd) => {
254
+ if (!opts.yes) {
255
+ throw new Error('Creating API keys is explicit. Re-run with "--yes" to confirm.');
256
+ }
257
+ const client = getClientFromCommand(cmd);
258
+ const body = {
259
+ name: opts.name,
260
+ permissions: []
261
+ };
262
+ if (opts.expires) body.expiresAt = opts.expires;
263
+ const result = await client.post("/api-keys", body);
264
+ formatOutput(result, getFormat(cmd));
265
+ });
266
+ keys.command("revoke").description("Revoke an API key").argument("<id>", "API key ID").option("--yes", "revoke without confirmation").action(async (id, opts, cmd) => {
267
+ if (!opts.yes) {
268
+ throw new Error('Revoking API keys is explicit. Re-run with "--yes" to confirm.');
269
+ }
270
+ const client = getClientFromCommand(cmd);
271
+ await client.delete(`/api-keys/${id}`);
272
+ process.stdout.write(`${chalk3.green("\u2713")} API key ${id} revoked.
273
+ `);
274
+ });
255
275
  }
276
+
277
+ // src/commands/records.ts
256
278
  function parseSortFlag(sort) {
257
279
  const [attribute, direction = "asc"] = sort.split(":");
258
280
  return JSON.stringify([{ attribute, direction }]);
259
281
  }
260
- function registerRecordsCommand(program2) {
261
- const records = program2.command("records").description("Manage records (CRUD + search)");
282
+ function registerRecordsCommand(program) {
283
+ const records = program.command("records").description("Manage records (CRUD + search)");
262
284
  records.command("list").description("List records for an object").argument("<object>", "object name (e.g. contacts)").option("--limit <n>", "max records to return").option("--offset <n>", "number of records to skip").option("--sort <sort>", 'sort rule as "attribute:direction"').option("--filter <json>", "filter state as JSON string").action(async (objectName, opts, cmd) => {
263
- const client = getClientFromCommand3(cmd);
285
+ const client = getClientFromCommand(cmd);
264
286
  const params = {};
265
287
  if (opts.limit) params.limit = opts.limit;
266
288
  if (opts.offset) params.offset = opts.offset;
267
289
  if (opts.sort) params.sorts = parseSortFlag(opts.sort);
268
290
  if (opts.filter) params.filters = opts.filter;
269
291
  const result = await client.get(`/records/${objectName}`, params);
270
- formatOutput(result, getFormat3(cmd));
292
+ formatOutput(result, getFormat(cmd));
271
293
  });
272
294
  records.command("get").description("Get a record by ID").argument("<object>", "object name").argument("<id>", "record ID").action(async (objectName, id, _opts, cmd) => {
273
- const client = getClientFromCommand3(cmd);
295
+ const client = getClientFromCommand(cmd);
274
296
  const result = await client.get(`/records/${objectName}/${id}`);
275
- formatOutput(result, getFormat3(cmd));
297
+ formatOutput(result, getFormat(cmd));
276
298
  });
277
299
  records.command("create").description("Create a new record").argument("<object>", "object name").option("--data <json>", "record data as JSON string").action(async (objectName, opts, cmd) => {
278
300
  const data = opts.data ? JSON.parse(opts.data) : {};
279
- const client = getClientFromCommand3(cmd);
280
- const result = await client.post(`/records/${objectName}`, data);
281
- formatOutput(result, getFormat3(cmd));
301
+ const client = getClientFromCommand(cmd);
302
+ const result = await client.post(`/records/${objectName}`, { data });
303
+ formatOutput(result, getFormat(cmd));
282
304
  });
283
305
  records.command("update").description("Update a record").argument("<object>", "object name").argument("<id>", "record ID").option("--data <json>", "fields to update as JSON string").action(async (objectName, id, opts, cmd) => {
284
306
  const data = opts.data ? JSON.parse(opts.data) : {};
285
- const client = getClientFromCommand3(cmd);
307
+ const client = getClientFromCommand(cmd);
286
308
  const result = await client.put(`/records/${objectName}/${id}`, data);
287
- formatOutput(result, getFormat3(cmd));
309
+ formatOutput(result, getFormat(cmd));
288
310
  });
289
311
  records.command("delete").description("Delete a record").argument("<object>", "object name").argument("<id>", "record ID").action(async (objectName, id, _opts, cmd) => {
290
- const client = getClientFromCommand3(cmd);
312
+ const client = getClientFromCommand(cmd);
291
313
  await client.delete(`/records/${objectName}/${id}`);
292
314
  process.stdout.write(`Record ${id} deleted.
293
315
  `);
294
316
  });
295
317
  records.command("search").description("Full-text search records").argument("<object>", "object name").requiredOption("--query <q>", "search query string").option("--limit <n>", "max records to return").option("--offset <n>", "number of records to skip").option("--sort <sort>", 'sort rule as "attribute:direction"').option("--filter <json>", "filter state as JSON string").action(async (objectName, opts, cmd) => {
296
- const client = getClientFromCommand3(cmd);
318
+ const client = getClientFromCommand(cmd);
297
319
  const params = { q: opts.query };
298
320
  if (opts.limit) params.limit = opts.limit;
299
321
  if (opts.offset) params.offset = opts.offset;
300
322
  if (opts.sort) params.sorts = parseSortFlag(opts.sort);
301
323
  if (opts.filter) params.filters = opts.filter;
302
324
  const result = await client.get(`/records/${objectName}/search`, params);
303
- formatOutput(result, getFormat3(cmd));
325
+ formatOutput(result, getFormat(cmd));
304
326
  });
305
327
  }
306
328
 
307
- // src/commands/schema.ts
308
- function getClientFromCommand4(cmd) {
309
- const root = cmd.optsWithGlobals();
310
- return createClient({ apiUrl: root.apiUrl, apiKey: root.apiKey });
329
+ // src/commands/root.ts
330
+ import { stdin as input, stdout as output } from "process";
331
+ import { createInterface } from "readline/promises";
332
+ import chalk4 from "chalk";
333
+
334
+ // src/config.ts
335
+ import { mkdir, readFile, rm, writeFile } from "fs/promises";
336
+ import { homedir } from "os";
337
+ import { dirname, join } from "path";
338
+ var DEFAULT_API_URL = "http://localhost:4100/v1";
339
+ function getDefaultApiUrl() {
340
+ return DEFAULT_API_URL;
311
341
  }
312
- function getFormat4(cmd) {
313
- return cmd.optsWithGlobals().format;
342
+ function getConfigPath() {
343
+ const configDir = process.env.STANDARDS_CONFIG_DIR ?? join(homedir(), ".standards");
344
+ return join(configDir, "config.json");
314
345
  }
315
- function registerSchemaCommand(program2) {
316
- const schema = program2.command("schema").description("Inspect schema objects and attributes");
346
+ async function readConfig() {
347
+ try {
348
+ const raw = await readFile(getConfigPath(), "utf8");
349
+ const parsed = JSON.parse(raw);
350
+ return {
351
+ currentProfile: parsed.currentProfile,
352
+ profiles: parsed.profiles ?? {}
353
+ };
354
+ } catch (error) {
355
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
356
+ return { profiles: {} };
357
+ }
358
+ throw error;
359
+ }
360
+ }
361
+ async function writeConfig(config) {
362
+ const path = getConfigPath();
363
+ await mkdir(dirname(path), { recursive: true, mode: 448 });
364
+ await writeFile(path, `${JSON.stringify(config, null, 2)}
365
+ `, { mode: 384 });
366
+ }
367
+ async function upsertProfile(input2) {
368
+ const config = await readConfig();
369
+ config.profiles[input2.name] = {
370
+ apiUrl: input2.apiUrl,
371
+ apiKey: input2.apiKey
372
+ };
373
+ config.currentProfile = input2.name;
374
+ await writeConfig(config);
375
+ }
376
+ async function setCurrentProfile(name) {
377
+ const config = await readConfig();
378
+ if (!config.profiles[name]) {
379
+ throw new Error(`Unknown Standards instance "${name}"`);
380
+ }
381
+ config.currentProfile = name;
382
+ await writeConfig(config);
383
+ }
384
+ async function removeProfile(name) {
385
+ const config = await readConfig();
386
+ const profileName = name ?? config.currentProfile;
387
+ if (!profileName) return;
388
+ delete config.profiles[profileName];
389
+ if (config.currentProfile === profileName) {
390
+ config.currentProfile = void 0;
391
+ }
392
+ await writeConfig(config);
393
+ }
394
+ async function listProfiles() {
395
+ const config = await readConfig();
396
+ return Object.entries(config.profiles).sort(([a], [b]) => a.localeCompare(b)).map(([name, profile]) => ({
397
+ name,
398
+ apiUrl: profile.apiUrl,
399
+ current: config.currentProfile === name
400
+ }));
401
+ }
402
+ async function getActiveProfile() {
403
+ const config = await readConfig();
404
+ if (!config.currentProfile) return null;
405
+ const profile = config.profiles[config.currentProfile];
406
+ if (!profile) return null;
407
+ return { name: config.currentProfile, ...profile };
408
+ }
409
+ async function resolveCliConfig(options) {
410
+ if (options.apiUrl || options.apiKey) {
411
+ return {
412
+ apiUrl: options.apiUrl ?? process.env.STANDARDS_API_URL ?? DEFAULT_API_URL,
413
+ apiKey: options.apiKey ?? process.env.STANDARDS_API_KEY
414
+ };
415
+ }
416
+ const config = await readConfig();
417
+ const profileName = options.instance ?? config.currentProfile;
418
+ if (profileName) {
419
+ const profile = config.profiles[profileName];
420
+ if (!profile) throw new Error(`Unknown Standards instance "${profileName}"`);
421
+ return {
422
+ apiUrl: profile.apiUrl,
423
+ apiKey: profile.apiKey,
424
+ profileName
425
+ };
426
+ }
427
+ return {
428
+ apiUrl: process.env.STANDARDS_API_URL ?? DEFAULT_API_URL,
429
+ apiKey: process.env.STANDARDS_API_KEY
430
+ };
431
+ }
432
+
433
+ // src/commands/root.ts
434
+ async function promptForMissingValue(label) {
435
+ const rl = createInterface({ input, output });
436
+ try {
437
+ const value = await rl.question(`${label}: `);
438
+ return value.trim();
439
+ } finally {
440
+ rl.close();
441
+ }
442
+ }
443
+ function registerRootCommands(program) {
444
+ program.command("login").description("Connect the CLI to a Standards instance").option("--url <url>", "Standards API URL", getDefaultApiUrl()).option("--key <key>", "API key to store for this instance").option("--name <name>", "local instance name", "local").action(async (opts) => {
445
+ const apiKey = opts.key ?? await promptForMissingValue("API key");
446
+ if (!apiKey) throw new Error("API key is required");
447
+ const client = createClient({ apiUrl: opts.url, apiKey });
448
+ await client.get("/api-keys");
449
+ await upsertProfile({ name: opts.name, apiUrl: opts.url, apiKey });
450
+ process.stdout.write(
451
+ `${chalk4.green("\u2713")} Standards instance "${opts.name}" saved and selected.
452
+ `
453
+ );
454
+ process.stdout.write(` API URL: ${opts.url}
455
+ `);
456
+ process.stdout.write(` API Key: ${apiKey.slice(0, 8)}...
457
+ `);
458
+ process.stdout.write(` Use it with: standards --instance ${opts.name} <command>
459
+ `);
460
+ });
461
+ program.command("use").description("Select the active Standards instance").argument("<name>", "instance name").action(async (name) => {
462
+ await setCurrentProfile(name);
463
+ process.stdout.write(`${chalk4.green("\u2713")} Standards instance "${name}" selected.
464
+ `);
465
+ });
466
+ program.command("instances").description("List configured Standards instances").action(async (_opts, cmd) => {
467
+ const profiles = await listProfiles();
468
+ formatOutput(profiles, getFormat(cmd));
469
+ });
470
+ program.command("current").description("Show the active Standards instance").action(async () => {
471
+ const profile = await getActiveProfile();
472
+ if (!profile) {
473
+ process.stdout.write(`No Standards instance selected. Run "standards login".
474
+ `);
475
+ return;
476
+ }
477
+ process.stdout.write(`${profile.name} ${profile.apiUrl}
478
+ `);
479
+ });
480
+ program.command("logout").description("Remove a Standards instance from local CLI config").argument("[name]", "instance name, defaults to current").action(async (name) => {
481
+ await removeProfile(name);
482
+ process.stdout.write(`${chalk4.green("\u2713")} Standards instance removed.
483
+ `);
484
+ });
485
+ }
486
+
487
+ // src/commands/schema.ts
488
+ function registerSchemaCommand(program) {
489
+ const schema = program.command("schema").description("Inspect schema objects and attributes");
317
490
  schema.command("list").description("List all schema objects").action(async (_opts, cmd) => {
318
- const client = getClientFromCommand4(cmd);
491
+ const client = getClientFromCommand(cmd);
319
492
  const result = await client.get("/schema/objects");
320
- formatOutput(result, getFormat4(cmd));
493
+ formatOutput(result, getFormat(cmd));
321
494
  });
322
495
  schema.command("inspect").description("Inspect an object (attributes, types, views)").argument("<object>", "object name or ID").action(async (objectName, _opts, cmd) => {
323
- const client = getClientFromCommand4(cmd);
496
+ const client = getClientFromCommand(cmd);
324
497
  const result = await client.get(`/schema/objects/${objectName}`);
325
- formatOutput(result, getFormat4(cmd));
498
+ formatOutput(result, getFormat(cmd));
326
499
  });
327
500
  }
328
501
 
329
- // src/bin.ts
330
- var program = new Command();
331
- program.name("standards").description("CLI to interact with Standards API").version("1.0.0-alpha.1").option("--format <format>", "output format (json, table, csv)", "json").option(
332
- "--api-url <url>",
333
- "API base URL",
334
- process.env.STANDARDS_API_URL ?? "http://localhost:4100"
335
- ).option("--api-key <key>", "API key for authentication", process.env.STANDARDS_API_KEY);
336
- registerRecordsCommand(program);
337
- registerSchemaCommand(program);
338
- registerDocumentsCommand(program);
339
- registerAuthCommand(program);
340
- program.hook("preAction", (_thisCommand, _actionCommand) => {
341
- const opts = program.opts();
342
- if (!opts.apiKey) {
343
- console.error(
344
- chalk3.red("\u2717 Error: No API key configured. Set STANDARDS_API_KEY or use --api-key")
345
- );
346
- process.exit(1);
347
- }
348
- });
349
- program.parseAsync(process.argv).catch((error) => {
350
- if (error instanceof ApiClientError) {
351
- if (error.statusCode > 0) {
352
- console.error(chalk3.red(`\u2717 Error (${error.statusCode}): ${error.message}`));
353
- } else {
354
- console.error(chalk3.red(`\u2717 Error: ${error.message}`));
502
+ // src/program.ts
503
+ var PUBLIC_COMMANDS = /* @__PURE__ */ new Set(["login", "use", "instances", "current", "logout", "help"]);
504
+ function isPublicCommand(actionCommand) {
505
+ if (PUBLIC_COMMANDS.has(actionCommand.name())) return true;
506
+ return actionCommand.parent?.name() === "auth" && actionCommand.name() === "help";
507
+ }
508
+ function createProgram() {
509
+ const program = new Command();
510
+ program.name("standards").description("CLI to interact with Standards API").version("1.0.0-alpha.3").option("--format <format>", "output format (json, table, csv)", "json").option("--api-url <url>", "API base URL").option("--api-key <key>", "API key for authentication").option("--instance <name>", "Standards instance profile to use");
511
+ registerRootCommands(program);
512
+ registerRecordsCommand(program);
513
+ registerSchemaCommand(program);
514
+ registerDocumentsCommand(program);
515
+ registerKeysCommand(program);
516
+ registerAuthCommand(program);
517
+ program.hook("preAction", async (_thisCommand, actionCommand) => {
518
+ const raw = program.opts();
519
+ const resolved = await resolveCliConfig({
520
+ apiUrl: raw.apiUrl,
521
+ apiKey: raw.apiKey,
522
+ instance: raw.instance
523
+ });
524
+ program.setOptionValue("apiUrl", resolved.apiUrl);
525
+ program.setOptionValue("apiKey", resolved.apiKey);
526
+ program.setOptionValue("profileName", resolved.profileName);
527
+ if (!(resolved.apiKey || isPublicCommand(actionCommand))) {
528
+ console.error(
529
+ chalk5.red(
530
+ `\u2717 Error: No Standards instance configured. Run "standards login" or pass --api-key.`
531
+ )
532
+ );
533
+ process.exit(1);
355
534
  }
356
- } else if (error instanceof Error) {
357
- console.error(chalk3.red(`\u2717 Error: ${error.message}`));
358
- }
359
- process.exit(1);
360
- });
535
+ });
536
+ return program;
537
+ }
538
+ async function runProgram(argv = process.argv) {
539
+ const program = createProgram();
540
+ await program.parseAsync(argv).catch((error) => {
541
+ if (error instanceof ApiClientError) {
542
+ if (error.statusCode > 0) {
543
+ console.error(chalk5.red(`\u2717 Error (${error.statusCode}): ${error.message}`));
544
+ } else {
545
+ console.error(chalk5.red(`\u2717 Error: ${error.message}`));
546
+ }
547
+ } else if (error instanceof Error) {
548
+ console.error(chalk5.red(`\u2717 Error: ${error.message}`));
549
+ }
550
+ process.exit(1);
551
+ });
552
+ }
553
+
554
+ // src/bin.ts
555
+ await runProgram();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stndrds/cli",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "CLI tool to interact with Standards API",
5
5
  "type": "module",
6
6
  "bin": {