@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.
- package/dist/bin.mjs +85 -17
- 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.
|
|
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.
|
|
23
|
-
"@standards/constants": "1.0.0-alpha.
|
|
24
|
-
"@standards/schema": "1.0.0-alpha.
|
|
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",
|