@standards/cli 1.0.0-alpha.388 → 1.0.0-alpha.390

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 +85 -17
  2. package/package.json +4 -4
package/dist/bin.mjs CHANGED
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
4
4
  import { styleText } from "node:util";
5
5
  import { StandardsRequestError, createTransport } from "@standards/client";
6
6
  import { Command } from "commander";
7
- import { DEVICE_CHANNEL_WORKER_CLOSE_PROTOCOL_VIOLATION, MEETING_RESPONSES, RECORDING_OVERRIDES, RECORD_ACCESS_ROLES, RESOURCE_VISIBILITIES, SchemaError, SchemaErrorCode, ValidationError, canonicalStringify, computeReconnectDelay, computeRetryDelay, deviceChannelUrl, diffSchemaState, formatByteSize, parseRecordAccessRole, parseSchemaState, parseServerFrame, schemaStateSourcePayload } from "@standards/schema";
7
+ import { CATALOG_KINDS, CATALOG_LOCALES, COUNT_MODES, DEVICE_CHANNEL_WORKER_CLOSE_PROTOCOL_VIOLATION, MEETING_RESPONSES, RECORDING_OVERRIDES, RECORD_ACCESS_ROLES, RESOURCE_VISIBILITIES, SchemaError, SchemaErrorCode, ValidationError, canonicalStringify, computeReconnectDelay, computeRetryDelay, deviceChannelUrl, diffSchemaState, formatByteSize, parseRecordAccessRole, parseSchemaState, parseServerFrame, schemaStateSourcePayload } from "@standards/schema";
8
8
  import Table from "cli-table3";
9
9
  import { createAppClient } from "@standards/client/app";
10
10
  import { homedir, hostname } from "node:os";
@@ -94,6 +94,15 @@ function getFormat(cmd) {
94
94
  function parseCsvList(value) {
95
95
  return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
96
96
  }
97
+ /**
98
+ * The API opts out of totals by default: an absent `countMode` yields no total.
99
+ * Reject unknown modes here so a typo surfaces as an error instead of a
100
+ * silently missing total.
101
+ */
102
+ function parseCountFlag(count) {
103
+ if (COUNT_MODES.includes(count)) return count;
104
+ throw new ValidationError(`Invalid --count value "${count}". Expected one of: ${COUNT_MODES.join(", ")}.`, []);
105
+ }
97
106
  function getClientFromCommand(cmd) {
98
107
  const root = getGlobalOptions(cmd);
99
108
  if (!(root.apiUrl && root.apiKey)) throw new Error("No Standards instance configured. Run \"standards login\" or pass --api-key.");
@@ -209,6 +218,77 @@ function registerBundlesCommand(program) {
209
218
  });
210
219
  }
211
220
  //#endregion
221
+ //#region src/commands/catalog.ts
222
+ /** Reject a typo instead of letting the API answer a 400 on a bare enum. */
223
+ function parseChoice(flag, value, choices) {
224
+ if (choices.includes(value)) return value;
225
+ throw new ValidationError(`${flag} must be one of: ${choices.join(", ")}`, []);
226
+ }
227
+ /** An empty selection installs nothing, so it is refused before the request. */
228
+ function parseSelection(opts) {
229
+ const selection = {};
230
+ if (opts.entries !== void 0) selection.entries = parseCsvList(opts.entries);
231
+ if (opts.packs !== void 0) selection.packs = parseCsvList(opts.packs);
232
+ if (!(selection.entries?.length || selection.packs?.length)) throw new ValidationError("Select at least one catalog entry (--entries) or pack (--packs)", []);
233
+ return selection;
234
+ }
235
+ /** `<entryId>=bind`, `<entryId>=skip` or `<entryId>=rename:<name>`, one per collision. */
236
+ function collectDecision(value, decisions) {
237
+ const separator = value.indexOf("=");
238
+ const entryId = value.slice(0, separator);
239
+ const choice = value.slice(separator + 1);
240
+ if (separator > 0 && (choice === "bind" || choice === "skip")) return {
241
+ ...decisions,
242
+ [entryId]: choice
243
+ };
244
+ if (separator > 0 && choice.startsWith("rename:") && choice.length > 7) return {
245
+ ...decisions,
246
+ [entryId]: { rename: choice.slice(7) }
247
+ };
248
+ throw new ValidationError(`--decision must read <entryId>=bind, <entryId>=skip or <entryId>=rename:<name> (received: ${value})`, []);
249
+ }
250
+ /** The flags `preview` and `install` share — both take the same selection. */
251
+ function withSelectionOptions(command) {
252
+ return command.option("--entries <ids>", "comma-separated catalog entry IDs to install").option("--packs <ids>", "comma-separated catalog pack IDs to install").option("--locale <locale>", `language to compile the pieces in (${CATALOG_LOCALES.join(", ")})`, "en").option("--with-samples", "also install the packs' sample records");
253
+ }
254
+ /**
255
+ * The pre-built catalog: objects, views and agents installed as copies the
256
+ * workspace owns. `preview` returns the plan and its fingerprint; `install`
257
+ * applies that same plan, refused if the workspace changed since.
258
+ */
259
+ function registerCatalogCommand(program) {
260
+ const catalog = program.command("catalog").description("Browse and install pre-built objects, views and agents");
261
+ catalog.command("list").description("List the catalog entries and packs, and whether each is installed").option("--kind <kind>", `restrict to one kind (${CATALOG_KINDS.join(", ")})`).option("--search <text>", "match labels and descriptions").option("--locale <locale>", `language of the labels (${CATALOG_LOCALES.join(", ")})`, "en").action(async (opts, cmd) => {
262
+ formatOutput(await getAppClientFromCommand(cmd).catalog.list({
263
+ locale: parseChoice("--locale", opts.locale, CATALOG_LOCALES),
264
+ ...opts.kind !== void 0 && { kind: parseChoice("--kind", opts.kind, CATALOG_KINDS) },
265
+ ...opts.search !== void 0 && { q: opts.search }
266
+ }), getFormat(cmd));
267
+ });
268
+ catalog.command("get").description("Get one catalog entry or pack, with the IDs it pulls in").argument("<id>", "catalog entry or pack ID").option("--locale <locale>", `language of the labels (${CATALOG_LOCALES.join(", ")})`, "en").action(async (id, opts, cmd) => {
269
+ formatOutput(await getAppClientFromCommand(cmd).catalog.read({
270
+ id,
271
+ locale: parseChoice("--locale", opts.locale, CATALOG_LOCALES)
272
+ }), getFormat(cmd));
273
+ });
274
+ withSelectionOptions(catalog.command("preview").description("Plan an install: what is new, what collides, and the plan's fingerprint")).action(async (opts, cmd) => {
275
+ formatOutput(await getAppClientFromCommand(cmd).catalog.preview({
276
+ selection: parseSelection(opts),
277
+ locale: parseChoice("--locale", opts.locale, CATALOG_LOCALES),
278
+ withSamples: opts.withSamples === true
279
+ }), getFormat(cmd));
280
+ });
281
+ withSelectionOptions(catalog.command("install").description("Install a previewed selection as workspace-owned copies").requiredOption("--fingerprint <fingerprint>", "the fingerprint `catalog preview` returned").option("--decision <entryId=choice>", "how to settle a collision: bind, skip or rename:<name> (repeatable)", collectDecision, {})).action(async (opts, cmd) => {
282
+ formatOutput(await getAppClientFromCommand(cmd).catalog.install({
283
+ selection: parseSelection(opts),
284
+ locale: parseChoice("--locale", opts.locale, CATALOG_LOCALES),
285
+ withSamples: opts.withSamples === true,
286
+ decisions: opts.decision,
287
+ fingerprint: opts.fingerprint
288
+ }), getFormat(cmd));
289
+ });
290
+ }
291
+ //#endregion
212
292
  //#region src/commands/codemod.ts
213
293
  /** Rewrites consumer code for a breaking SDK change. */
214
294
  function registerCodemodCommand(program) {
@@ -1644,11 +1724,12 @@ function registerMeetingsCommand(program) {
1644
1724
  meetings.command("get").description("Get one meeting, with its participants and linked records").argument("<id>", "meeting ID").action(async (id, _opts, cmd) => {
1645
1725
  formatOutput(await getAppClientFromCommand(cmd).meetings.get({ meetingId: id }), getFormat(cmd));
1646
1726
  });
1647
- withQueryOptions(meetings.command("for-record").description("List the meetings a record's email addresses appear in").argument("<recordId>", "record ID").option("--email-attributes <ids>", "comma-separated email attribute IDs to match participants on")).action(async (recordId, opts, cmd) => {
1727
+ withQueryOptions(meetings.command("for-record").description("List the meetings a record's email addresses appear in").argument("<recordId>", "record ID").option("--email-attributes <ids>", "comma-separated email attribute IDs to match participants on").option("--count <mode>", "total count mode (estimated, exact); omit for no total")).action(async (recordId, opts, cmd) => {
1648
1728
  formatOutput(await getAppClientFromCommand(cmd).meetings.forRecord({
1649
1729
  recordId,
1650
1730
  ...opts.emailAttributes !== void 0 && { emailAttributeIds: parseCsvList(opts.emailAttributes) },
1651
- query: buildQuery(opts)
1731
+ query: buildQuery(opts),
1732
+ ...opts.count !== void 0 && { countMode: parseCountFlag(opts.count) }
1652
1733
  }), getFormat(cmd));
1653
1734
  });
1654
1735
  meetings.command("transcript").description("Read a meeting's completed transcript").argument("<id>", "meeting ID").action(async (id, _opts, cmd) => {
@@ -1741,20 +1822,6 @@ function parseSortFlag(sort) {
1741
1822
  direction
1742
1823
  }];
1743
1824
  }
1744
- const COUNT_MODES = [
1745
- "none",
1746
- "estimated",
1747
- "exact"
1748
- ];
1749
- /**
1750
- * The API opts out of totals by default: an absent or unrecognized `countMode`
1751
- * yields `page.total: null`. Reject unknown modes here so a typo surfaces as an
1752
- * error instead of a silently missing total.
1753
- */
1754
- function parseCountFlag(count) {
1755
- if (COUNT_MODES.includes(count)) return count;
1756
- throw new Error(`Invalid --count value "${count}". Expected one of: ${COUNT_MODES.join(", ")}.`);
1757
- }
1758
1825
  /** Build the shared list/search request body from common query flags. */
1759
1826
  function buildQueryBody(opts) {
1760
1827
  const body = {};
@@ -2034,6 +2101,7 @@ function createProgram() {
2034
2101
  registerInvitationsCommand(program);
2035
2102
  registerAuthCommand(program);
2036
2103
  registerBundlesCommand(program);
2104
+ registerCatalogCommand(program);
2037
2105
  registerSourcesCommand(program);
2038
2106
  registerCodemodCommand(program);
2039
2107
  registerConnectorsCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standards/cli",
3
- "version": "1.0.0-alpha.388",
3
+ "version": "1.0.0-alpha.390",
4
4
  "description": "CLI tool to interact with Standards API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,9 +19,9 @@
19
19
  "commander": "^13.1.0",
20
20
  "typescript": "^5.6.3",
21
21
  "ws": "8.21.1",
22
- "@standards/client": "1.0.0-alpha.388",
23
- "@standards/constants": "1.0.0-alpha.388",
24
- "@standards/schema": "1.0.0-alpha.388"
22
+ "@standards/client": "1.0.0-alpha.390",
23
+ "@standards/constants": "1.0.0-alpha.390",
24
+ "@standards/schema": "1.0.0-alpha.390"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^25.6.0",