zinkee 0.1.41 → 0.1.42
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/AGENTS.md +1 -0
- package/README.md +23 -0
- package/dist/index.js +435 -181
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/formulas.test.ts +65 -0
- package/src/api/formulas.ts +67 -0
- package/src/command-registry.ts +21 -0
- package/src/commands/formulas.test.ts +194 -0
- package/src/commands/formulas.ts +243 -0
- package/src/program.ts +2 -0
- package/src/utils/examples.ts +54 -0
package/dist/index.js
CHANGED
|
@@ -9,6 +9,27 @@ import chalk from "chalk";
|
|
|
9
9
|
var readOutput = "table-json";
|
|
10
10
|
var writeOutput = "json-only";
|
|
11
11
|
var commandRegistry = {
|
|
12
|
+
"formulas recompute field": {
|
|
13
|
+
command: "formulas recompute field",
|
|
14
|
+
accessLevel: "write",
|
|
15
|
+
supportsExample: true,
|
|
16
|
+
supportsRaw: false,
|
|
17
|
+
output: writeOutput
|
|
18
|
+
},
|
|
19
|
+
"formulas recompute schema": {
|
|
20
|
+
command: "formulas recompute schema",
|
|
21
|
+
accessLevel: "write",
|
|
22
|
+
supportsExample: true,
|
|
23
|
+
supportsRaw: false,
|
|
24
|
+
output: writeOutput
|
|
25
|
+
},
|
|
26
|
+
"formulas recompute workspace": {
|
|
27
|
+
command: "formulas recompute workspace",
|
|
28
|
+
accessLevel: "write",
|
|
29
|
+
supportsExample: true,
|
|
30
|
+
supportsRaw: false,
|
|
31
|
+
output: writeOutput
|
|
32
|
+
},
|
|
12
33
|
"config path": {
|
|
13
34
|
command: "config path",
|
|
14
35
|
accessLevel: "read",
|
|
@@ -2229,6 +2250,60 @@ function buildCommandExamples(examples) {
|
|
|
2229
2250
|
}
|
|
2230
2251
|
var SAMPLE_UUID = "550e8400-e29b-41d4-a716-446655440001";
|
|
2231
2252
|
var specificExamples = {
|
|
2253
|
+
"formulas recompute field": buildCommandExamples([
|
|
2254
|
+
{
|
|
2255
|
+
description: "Queue a full recalculation of one formula column.",
|
|
2256
|
+
command: "zinkee --json formulas recompute field invoices total",
|
|
2257
|
+
raw: `{
|
|
2258
|
+
"scope": "FIELD",
|
|
2259
|
+
"schema": "invoices",
|
|
2260
|
+
"field": "total"
|
|
2261
|
+
}`,
|
|
2262
|
+
response: `{
|
|
2263
|
+
"requestId": "02ab5d47-cb5f-4eb2-afb8-e9a3a9eb34d4",
|
|
2264
|
+
"scope": "FIELD",
|
|
2265
|
+
"formulaCount": 1,
|
|
2266
|
+
"skippedFormulaCount": 0,
|
|
2267
|
+
"eventsQueued": 1,
|
|
2268
|
+
"status": "QUEUED"
|
|
2269
|
+
}`
|
|
2270
|
+
}
|
|
2271
|
+
]),
|
|
2272
|
+
"formulas recompute schema": buildCommandExamples([
|
|
2273
|
+
{
|
|
2274
|
+
description: "Queue recalculation of every active formula in one schema.",
|
|
2275
|
+
command: "zinkee --json formulas recompute schema invoices --yes",
|
|
2276
|
+
raw: `{
|
|
2277
|
+
"scope": "SCHEMA",
|
|
2278
|
+
"schema": "invoices"
|
|
2279
|
+
}`,
|
|
2280
|
+
response: `{
|
|
2281
|
+
"requestId": "02ab5d47-cb5f-4eb2-afb8-e9a3a9eb34d4",
|
|
2282
|
+
"scope": "SCHEMA",
|
|
2283
|
+
"formulaCount": 8,
|
|
2284
|
+
"skippedFormulaCount": 1,
|
|
2285
|
+
"eventsQueued": 8,
|
|
2286
|
+
"status": "QUEUED"
|
|
2287
|
+
}`
|
|
2288
|
+
}
|
|
2289
|
+
]),
|
|
2290
|
+
"formulas recompute workspace": buildCommandExamples([
|
|
2291
|
+
{
|
|
2292
|
+
description: "Queue recalculation of every active formula in the workspace.",
|
|
2293
|
+
command: "zinkee --json formulas recompute workspace --yes",
|
|
2294
|
+
raw: `{
|
|
2295
|
+
"scope": "WORKSPACE"
|
|
2296
|
+
}`,
|
|
2297
|
+
response: `{
|
|
2298
|
+
"requestId": "02ab5d47-cb5f-4eb2-afb8-e9a3a9eb34d4",
|
|
2299
|
+
"scope": "WORKSPACE",
|
|
2300
|
+
"formulaCount": 24,
|
|
2301
|
+
"skippedFormulaCount": 2,
|
|
2302
|
+
"eventsQueued": 24,
|
|
2303
|
+
"status": "QUEUED"
|
|
2304
|
+
}`
|
|
2305
|
+
}
|
|
2306
|
+
]),
|
|
2232
2307
|
"profiles list": buildCommandExamples([
|
|
2233
2308
|
{
|
|
2234
2309
|
description: "List all local profiles. The CLI always redacts the apiKey to ******** plus the last 4 chars.",
|
|
@@ -6573,7 +6648,7 @@ ${index + 1}. ${example.description}
|
|
|
6573
6648
|
|
|
6574
6649
|
// src/program.ts
|
|
6575
6650
|
import { createRequire } from "module";
|
|
6576
|
-
import { Command as
|
|
6651
|
+
import { Command as Command12 } from "commander";
|
|
6577
6652
|
|
|
6578
6653
|
// src/config.ts
|
|
6579
6654
|
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -10530,42 +10605,220 @@ function registerFilesCommands(program, options = {}) {
|
|
|
10530
10605
|
});
|
|
10531
10606
|
}
|
|
10532
10607
|
|
|
10533
|
-
// src/commands/
|
|
10608
|
+
// src/commands/formulas.ts
|
|
10534
10609
|
import { InvalidArgumentError as InvalidArgumentError6 } from "commander";
|
|
10535
10610
|
|
|
10536
|
-
// src/api/
|
|
10611
|
+
// src/api/formulas.ts
|
|
10537
10612
|
function selectorValue6(selector) {
|
|
10538
10613
|
return selector.value;
|
|
10539
10614
|
}
|
|
10615
|
+
function toRequestBody(input) {
|
|
10616
|
+
if (input.scope === "FIELD") {
|
|
10617
|
+
return {
|
|
10618
|
+
scope: input.scope,
|
|
10619
|
+
schema: selectorValue6(input.schema),
|
|
10620
|
+
field: selectorValue6(input.field)
|
|
10621
|
+
};
|
|
10622
|
+
}
|
|
10623
|
+
if (input.scope === "SCHEMA") {
|
|
10624
|
+
return {
|
|
10625
|
+
scope: input.scope,
|
|
10626
|
+
schema: selectorValue6(input.schema)
|
|
10627
|
+
};
|
|
10628
|
+
}
|
|
10629
|
+
return { scope: input.scope };
|
|
10630
|
+
}
|
|
10631
|
+
var FormulasApi = class {
|
|
10632
|
+
constructor(client) {
|
|
10633
|
+
this.client = client;
|
|
10634
|
+
}
|
|
10635
|
+
recompute(input) {
|
|
10636
|
+
return this.client.requestJson(
|
|
10637
|
+
"/api/v2/formulas:recompute",
|
|
10638
|
+
{
|
|
10639
|
+
method: "POST",
|
|
10640
|
+
headers: {
|
|
10641
|
+
"content-type": "application/json"
|
|
10642
|
+
},
|
|
10643
|
+
body: JSON.stringify(toRequestBody(input))
|
|
10644
|
+
}
|
|
10645
|
+
);
|
|
10646
|
+
}
|
|
10647
|
+
};
|
|
10648
|
+
|
|
10649
|
+
// src/commands/formulas.ts
|
|
10650
|
+
function getCommandIo7(stdout) {
|
|
10651
|
+
return stdout ?? process.stdout;
|
|
10652
|
+
}
|
|
10653
|
+
function writeLine7(stdout, value) {
|
|
10654
|
+
stdout.write(`${value}
|
|
10655
|
+
`);
|
|
10656
|
+
}
|
|
10657
|
+
function getGlobalOptions7(command) {
|
|
10658
|
+
return command.optsWithGlobals();
|
|
10659
|
+
}
|
|
10660
|
+
function toConfigurationError7(filePath, error) {
|
|
10661
|
+
if (error instanceof CliError) {
|
|
10662
|
+
throw error;
|
|
10663
|
+
}
|
|
10664
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
10665
|
+
throw new CliError("configuration_error", `Config file not found at ${filePath}.`);
|
|
10666
|
+
}
|
|
10667
|
+
if (error instanceof Error) {
|
|
10668
|
+
throw new CliError("configuration_error", error.message);
|
|
10669
|
+
}
|
|
10670
|
+
throw error;
|
|
10671
|
+
}
|
|
10672
|
+
function createFormulasApi(command, filePath) {
|
|
10673
|
+
try {
|
|
10674
|
+
const config = readRuntimeConfig(filePath);
|
|
10675
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions7(command));
|
|
10676
|
+
if (!runtime.baseUrl) {
|
|
10677
|
+
throw new CliError(
|
|
10678
|
+
"configuration_error",
|
|
10679
|
+
`Resolved profile "${runtime.profile}" is missing a base URL.`
|
|
10680
|
+
);
|
|
10681
|
+
}
|
|
10682
|
+
return {
|
|
10683
|
+
api: new FormulasApi(
|
|
10684
|
+
new ApiClient({
|
|
10685
|
+
baseUrl: runtime.baseUrl,
|
|
10686
|
+
apiKey: runtime.apiKey
|
|
10687
|
+
})
|
|
10688
|
+
),
|
|
10689
|
+
json: runtime.json,
|
|
10690
|
+
readOnly: runtime.readOnly
|
|
10691
|
+
};
|
|
10692
|
+
} catch (error) {
|
|
10693
|
+
toConfigurationError7(filePath, error);
|
|
10694
|
+
}
|
|
10695
|
+
}
|
|
10696
|
+
function ensureWritable6(commandName, readOnly) {
|
|
10697
|
+
if (readOnly) {
|
|
10698
|
+
throw new CliError(
|
|
10699
|
+
"command_not_allowed_in_read_only_mode",
|
|
10700
|
+
`Command "${commandName}" is not allowed in read-only mode.`,
|
|
10701
|
+
{
|
|
10702
|
+
commandMode: "write",
|
|
10703
|
+
executionMode: "read-only"
|
|
10704
|
+
}
|
|
10705
|
+
);
|
|
10706
|
+
}
|
|
10707
|
+
}
|
|
10708
|
+
function ensureConfirmed(commandName, confirmed) {
|
|
10709
|
+
if (!confirmed) {
|
|
10710
|
+
throw new CliError(
|
|
10711
|
+
"invalid_cli_usage",
|
|
10712
|
+
`Command "${commandName}" requires --yes because it may enqueue a large recalculation.`
|
|
10713
|
+
);
|
|
10714
|
+
}
|
|
10715
|
+
}
|
|
10716
|
+
function parseUuidOrSlugSelector6(input) {
|
|
10717
|
+
try {
|
|
10718
|
+
return normalizeUuidOrSlug(input);
|
|
10719
|
+
} catch (error) {
|
|
10720
|
+
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
10721
|
+
throw new InvalidArgumentError6(message);
|
|
10722
|
+
}
|
|
10723
|
+
}
|
|
10724
|
+
function emitResult(stdout, commandName, result, configPath, json) {
|
|
10725
|
+
if (json) {
|
|
10726
|
+
writeLine7(
|
|
10727
|
+
stdout,
|
|
10728
|
+
JSON.stringify(buildJsonSuccess(result, { command: commandName, configPath }))
|
|
10729
|
+
);
|
|
10730
|
+
return;
|
|
10731
|
+
}
|
|
10732
|
+
writeLine7(
|
|
10733
|
+
stdout,
|
|
10734
|
+
`Queued ${result.eventsQueued} formula recalculation event(s) for ${result.scope.toLowerCase()} scope (request ${result.requestId}).`
|
|
10735
|
+
);
|
|
10736
|
+
}
|
|
10737
|
+
async function recompute(command, commandName, input, options, requireConfirmation, confirmed) {
|
|
10738
|
+
const configPath = options.configPath ?? defaultConfigPath;
|
|
10739
|
+
const stdout = getCommandIo7(options.stdout);
|
|
10740
|
+
const { api, json, readOnly } = createFormulasApi(command, configPath);
|
|
10741
|
+
ensureWritable6(commandName, readOnly);
|
|
10742
|
+
if (requireConfirmation) {
|
|
10743
|
+
ensureConfirmed(commandName, confirmed);
|
|
10744
|
+
}
|
|
10745
|
+
const result = await api.recompute(input);
|
|
10746
|
+
emitResult(stdout, commandName, result, configPath, json);
|
|
10747
|
+
}
|
|
10748
|
+
function registerFormulasCommands(program, options = {}) {
|
|
10749
|
+
const formulas = program.command("formulas").description("Recalculate formula values");
|
|
10750
|
+
const recomputeCommand = formulas.command("recompute").description("Queue a full formula recalculation");
|
|
10751
|
+
recomputeCommand.command("field").description("Queue recalculation of one formula column").argument("<schema>", "schema UUID or slug", parseUuidOrSlugSelector6).argument("<field>", "formula field UUID or slug", parseUuidOrSlugSelector6).action(
|
|
10752
|
+
async function action(schema, field) {
|
|
10753
|
+
await recompute(
|
|
10754
|
+
this,
|
|
10755
|
+
"formulas recompute field",
|
|
10756
|
+
{ scope: "FIELD", schema, field },
|
|
10757
|
+
options,
|
|
10758
|
+
false
|
|
10759
|
+
);
|
|
10760
|
+
}
|
|
10761
|
+
);
|
|
10762
|
+
recomputeCommand.command("schema").description("Queue recalculation of all active formulas in one schema").argument("<schema>", "schema UUID or slug", parseUuidOrSlugSelector6).option("--yes", "confirm the potentially expensive recalculation").action(
|
|
10763
|
+
async function action(schema, commandOptions) {
|
|
10764
|
+
await recompute(
|
|
10765
|
+
this,
|
|
10766
|
+
"formulas recompute schema",
|
|
10767
|
+
{ scope: "SCHEMA", schema },
|
|
10768
|
+
options,
|
|
10769
|
+
true,
|
|
10770
|
+
commandOptions.yes
|
|
10771
|
+
);
|
|
10772
|
+
}
|
|
10773
|
+
);
|
|
10774
|
+
recomputeCommand.command("workspace").description("Queue recalculation of all active formulas in the workspace").option("--yes", "confirm the potentially expensive recalculation").action(async function action(commandOptions) {
|
|
10775
|
+
await recompute(
|
|
10776
|
+
this,
|
|
10777
|
+
"formulas recompute workspace",
|
|
10778
|
+
{ scope: "WORKSPACE" },
|
|
10779
|
+
options,
|
|
10780
|
+
true,
|
|
10781
|
+
commandOptions.yes
|
|
10782
|
+
);
|
|
10783
|
+
});
|
|
10784
|
+
}
|
|
10785
|
+
|
|
10786
|
+
// src/commands/logs.ts
|
|
10787
|
+
import { InvalidArgumentError as InvalidArgumentError7 } from "commander";
|
|
10788
|
+
|
|
10789
|
+
// src/api/logs.ts
|
|
10790
|
+
function selectorValue7(selector) {
|
|
10791
|
+
return selector.value;
|
|
10792
|
+
}
|
|
10540
10793
|
var LogsApi = class {
|
|
10541
10794
|
constructor(client) {
|
|
10542
10795
|
this.client = client;
|
|
10543
10796
|
}
|
|
10544
10797
|
listLogs(schema, recordId) {
|
|
10545
10798
|
return this.client.getJson(
|
|
10546
|
-
`/api/v2/schemas/${
|
|
10799
|
+
`/api/v2/schemas/${selectorValue7(schema)}/records/${recordId}/logs`
|
|
10547
10800
|
);
|
|
10548
10801
|
}
|
|
10549
10802
|
};
|
|
10550
10803
|
|
|
10551
10804
|
// src/commands/logs.ts
|
|
10552
|
-
function
|
|
10805
|
+
function getCommandIo8(stdout) {
|
|
10553
10806
|
return stdout ?? process.stdout;
|
|
10554
10807
|
}
|
|
10555
|
-
function
|
|
10808
|
+
function writeLine8(stdout, value) {
|
|
10556
10809
|
stdout.write(`${value}
|
|
10557
10810
|
`);
|
|
10558
10811
|
}
|
|
10559
|
-
function
|
|
10812
|
+
function getGlobalOptions8(command) {
|
|
10560
10813
|
return command.optsWithGlobals();
|
|
10561
10814
|
}
|
|
10562
10815
|
function emitJson7(stdout, commandName, data, ..._extra) {
|
|
10563
|
-
|
|
10816
|
+
writeLine8(
|
|
10564
10817
|
stdout,
|
|
10565
10818
|
JSON.stringify(buildJsonSuccess(data, { command: commandName }))
|
|
10566
10819
|
);
|
|
10567
10820
|
}
|
|
10568
|
-
function
|
|
10821
|
+
function toConfigurationError8(filePath, error) {
|
|
10569
10822
|
if (error instanceof CliError) {
|
|
10570
10823
|
throw error;
|
|
10571
10824
|
}
|
|
@@ -10580,7 +10833,7 @@ function toConfigurationError7(filePath, error) {
|
|
|
10580
10833
|
function createLogsApi(command, filePath) {
|
|
10581
10834
|
try {
|
|
10582
10835
|
const config = readRuntimeConfig(filePath);
|
|
10583
|
-
const runtime = resolveRuntimeContext(config,
|
|
10836
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions8(command));
|
|
10584
10837
|
if (!runtime.baseUrl) {
|
|
10585
10838
|
throw new CliError(
|
|
10586
10839
|
"configuration_error",
|
|
@@ -10597,15 +10850,15 @@ function createLogsApi(command, filePath) {
|
|
|
10597
10850
|
json: runtime.json
|
|
10598
10851
|
};
|
|
10599
10852
|
} catch (error) {
|
|
10600
|
-
|
|
10853
|
+
toConfigurationError8(filePath, error);
|
|
10601
10854
|
}
|
|
10602
10855
|
}
|
|
10603
|
-
function
|
|
10856
|
+
function parseUuidOrSlugSelector7(input) {
|
|
10604
10857
|
try {
|
|
10605
10858
|
return normalizeUuidOrSlug(input);
|
|
10606
10859
|
} catch (error) {
|
|
10607
10860
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
10608
|
-
throw new
|
|
10861
|
+
throw new InvalidArgumentError7(message);
|
|
10609
10862
|
}
|
|
10610
10863
|
}
|
|
10611
10864
|
function isJsonObject5(value) {
|
|
@@ -10625,9 +10878,9 @@ function emitTable3(stdout, data) {
|
|
|
10625
10878
|
}
|
|
10626
10879
|
function registerLogsCommands(program, options = {}) {
|
|
10627
10880
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
10628
|
-
const stdout =
|
|
10881
|
+
const stdout = getCommandIo8(options.stdout);
|
|
10629
10882
|
const logs = program.command("logs").description("Inspect record change logs");
|
|
10630
|
-
logs.command("list").description("List change logs for a record").argument("<schema>", "schema uuid or slug",
|
|
10883
|
+
logs.command("list").description("List change logs for a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema, record) {
|
|
10631
10884
|
const { api, json } = createLogsApi(this, filePath);
|
|
10632
10885
|
const data = await api.listLogs(schema, record.value);
|
|
10633
10886
|
if (json) {
|
|
@@ -10640,7 +10893,7 @@ function registerLogsCommands(program, options = {}) {
|
|
|
10640
10893
|
|
|
10641
10894
|
// src/commands/navigation.ts
|
|
10642
10895
|
import { readFileSync as readFileSync7 } from "fs";
|
|
10643
|
-
import { InvalidArgumentError as
|
|
10896
|
+
import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
|
|
10644
10897
|
|
|
10645
10898
|
// src/api/navigation.ts
|
|
10646
10899
|
function jsonOptions5(body, method) {
|
|
@@ -10652,7 +10905,7 @@ function jsonOptions5(body, method) {
|
|
|
10652
10905
|
body: JSON.stringify(body)
|
|
10653
10906
|
};
|
|
10654
10907
|
}
|
|
10655
|
-
function
|
|
10908
|
+
function selectorValue8(selector) {
|
|
10656
10909
|
return selector.value;
|
|
10657
10910
|
}
|
|
10658
10911
|
var NavigationApi = class {
|
|
@@ -10670,13 +10923,13 @@ var NavigationApi = class {
|
|
|
10670
10923
|
}
|
|
10671
10924
|
updateFolder(folder, body) {
|
|
10672
10925
|
return this.client.requestJson(
|
|
10673
|
-
`/api/v2/navigation/folders/${
|
|
10926
|
+
`/api/v2/navigation/folders/${selectorValue8(folder)}`,
|
|
10674
10927
|
jsonOptions5(body, "PATCH")
|
|
10675
10928
|
);
|
|
10676
10929
|
}
|
|
10677
10930
|
deleteFolder(folder) {
|
|
10678
10931
|
return this.client.requestJson(
|
|
10679
|
-
`/api/v2/navigation/folders/${
|
|
10932
|
+
`/api/v2/navigation/folders/${selectorValue8(folder)}`,
|
|
10680
10933
|
{ method: "DELETE" }
|
|
10681
10934
|
);
|
|
10682
10935
|
}
|
|
@@ -10689,20 +10942,20 @@ var NavigationApi = class {
|
|
|
10689
10942
|
};
|
|
10690
10943
|
|
|
10691
10944
|
// src/commands/navigation.ts
|
|
10692
|
-
function
|
|
10945
|
+
function getCommandIo9(stdout) {
|
|
10693
10946
|
return stdout ?? process.stdout;
|
|
10694
10947
|
}
|
|
10695
|
-
function
|
|
10948
|
+
function writeLine9(stdout, value) {
|
|
10696
10949
|
stdout.write(`${value}
|
|
10697
10950
|
`);
|
|
10698
10951
|
}
|
|
10699
|
-
function
|
|
10952
|
+
function getGlobalOptions9(command) {
|
|
10700
10953
|
return command.optsWithGlobals();
|
|
10701
10954
|
}
|
|
10702
10955
|
function emitJson8(stdout, commandName, data, configPath) {
|
|
10703
|
-
|
|
10956
|
+
writeLine9(stdout, JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath })));
|
|
10704
10957
|
}
|
|
10705
|
-
function
|
|
10958
|
+
function toConfigurationError9(filePath, error) {
|
|
10706
10959
|
if (error instanceof CliError) {
|
|
10707
10960
|
throw error;
|
|
10708
10961
|
}
|
|
@@ -10717,7 +10970,7 @@ function toConfigurationError8(filePath, error) {
|
|
|
10717
10970
|
function createNavigationApi(command, filePath) {
|
|
10718
10971
|
try {
|
|
10719
10972
|
const config = readRuntimeConfig(filePath);
|
|
10720
|
-
const runtime = resolveRuntimeContext(config,
|
|
10973
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions9(command));
|
|
10721
10974
|
if (!runtime.baseUrl) {
|
|
10722
10975
|
throw new CliError("configuration_error", `Resolved profile "${runtime.profile}" is missing a base URL.`);
|
|
10723
10976
|
}
|
|
@@ -10732,10 +10985,10 @@ function createNavigationApi(command, filePath) {
|
|
|
10732
10985
|
readOnly: runtime.readOnly
|
|
10733
10986
|
};
|
|
10734
10987
|
} catch (error) {
|
|
10735
|
-
|
|
10988
|
+
toConfigurationError9(filePath, error);
|
|
10736
10989
|
}
|
|
10737
10990
|
}
|
|
10738
|
-
function
|
|
10991
|
+
function ensureWritable7(commandName, readOnly, mode) {
|
|
10739
10992
|
if (readOnly) {
|
|
10740
10993
|
throw new CliError(
|
|
10741
10994
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -10744,12 +10997,12 @@ function ensureWritable6(commandName, readOnly, mode) {
|
|
|
10744
10997
|
);
|
|
10745
10998
|
}
|
|
10746
10999
|
}
|
|
10747
|
-
function
|
|
11000
|
+
function parseUuidOrSlugSelector8(input) {
|
|
10748
11001
|
try {
|
|
10749
11002
|
return normalizeUuidOrSlug(input);
|
|
10750
11003
|
} catch (error) {
|
|
10751
11004
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
10752
|
-
throw new
|
|
11005
|
+
throw new InvalidArgumentError8(message);
|
|
10753
11006
|
}
|
|
10754
11007
|
}
|
|
10755
11008
|
function parseInteger(value, flagName) {
|
|
@@ -10828,7 +11081,7 @@ function folderRows2(folders) {
|
|
|
10828
11081
|
}
|
|
10829
11082
|
function registerNavigationCommands(program, options = {}) {
|
|
10830
11083
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
10831
|
-
const stdout =
|
|
11084
|
+
const stdout = getCommandIo9(options.stdout);
|
|
10832
11085
|
const navigation = program.command("navigation").description("Manage workspace navigation");
|
|
10833
11086
|
const folders = navigation.command("folders").description("Manage navigation folders");
|
|
10834
11087
|
folders.command("list").description("List navigation folders").action(async function action() {
|
|
@@ -10840,7 +11093,7 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
10840
11093
|
}
|
|
10841
11094
|
printTable(folderRows2(data), ["id", "order", "name", "resourceCount"], stdout);
|
|
10842
11095
|
});
|
|
10843
|
-
folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name",
|
|
11096
|
+
folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).action(async function action(folder) {
|
|
10844
11097
|
const { api, json } = createNavigationApi(this, filePath);
|
|
10845
11098
|
const data = await api.listFolders();
|
|
10846
11099
|
const resolved = resolveFolder2(data, folder);
|
|
@@ -10852,17 +11105,17 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
10852
11105
|
});
|
|
10853
11106
|
folders.command("create").description("Create a navigation folder").requiredOption("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)").option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"color":"blue","icon":"chart-line"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(commandOptions) {
|
|
10854
11107
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
10855
|
-
|
|
11108
|
+
ensureWritable7("navigation folders create", readOnly, "write");
|
|
10856
11109
|
const data = await api.createFolder(buildFolderBody(commandOptions));
|
|
10857
11110
|
if (json) {
|
|
10858
11111
|
emitJson8(stdout, "navigation folders create", data, filePath);
|
|
10859
11112
|
return;
|
|
10860
11113
|
}
|
|
10861
|
-
|
|
11114
|
+
writeLine9(stdout, `Created navigation folder "${String(data.name ?? commandOptions.name)}".`);
|
|
10862
11115
|
});
|
|
10863
|
-
folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name",
|
|
11116
|
+
folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).option("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)").option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"color":"blue","icon":"chart-line"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(folder, commandOptions) {
|
|
10864
11117
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
10865
|
-
|
|
11118
|
+
ensureWritable7("navigation folders update", readOnly, "write");
|
|
10866
11119
|
const allFolders = await api.listFolders();
|
|
10867
11120
|
const resolved = resolveFolder2(allFolders, folder);
|
|
10868
11121
|
const body = buildFolderBody(commandOptions);
|
|
@@ -10874,11 +11127,11 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
10874
11127
|
emitJson8(stdout, "navigation folders update", data, filePath);
|
|
10875
11128
|
return;
|
|
10876
11129
|
}
|
|
10877
|
-
|
|
11130
|
+
writeLine9(stdout, `Updated navigation folder "${String(data.name ?? resolved.name ?? resolved.id)}".`);
|
|
10878
11131
|
});
|
|
10879
|
-
folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name",
|
|
11132
|
+
folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).action(async function action(folder) {
|
|
10880
11133
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
10881
|
-
|
|
11134
|
+
ensureWritable7("navigation folders delete", readOnly, "destructive");
|
|
10882
11135
|
const allFolders = await api.listFolders();
|
|
10883
11136
|
const resolved = resolveFolder2(allFolders, folder);
|
|
10884
11137
|
const data = await api.deleteFolder({ kind: "uuid", value: resolved.id });
|
|
@@ -10886,15 +11139,15 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
10886
11139
|
emitJson8(stdout, "navigation folders delete", data, filePath);
|
|
10887
11140
|
return;
|
|
10888
11141
|
}
|
|
10889
|
-
|
|
11142
|
+
writeLine9(stdout, `Deleted navigation folder "${resolved.name ?? resolved.id}".`);
|
|
10890
11143
|
});
|
|
10891
11144
|
navigation.command("resources").description("Manage navigation resources").command("move").description(
|
|
10892
11145
|
"Move a schema into a navigation folder. Only schemas can be moved (the navigation menu holds databases); schedules and sub-schemas follow their parent schema. Use the root folder UUID 00000000-0000-0000-0000-000000000000 to move it back to the workspace root."
|
|
10893
11146
|
).argument("<resource>", "schema UUID").requiredOption("--to <folder>", "target folder UUID or exact name").action(async function action(resourceId, commandOptions) {
|
|
10894
11147
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
10895
|
-
|
|
11148
|
+
ensureWritable7("navigation resources move", readOnly, "write");
|
|
10896
11149
|
const allFolders = await api.listFolders();
|
|
10897
|
-
const resolved = resolveFolder2(allFolders,
|
|
11150
|
+
const resolved = resolveFolder2(allFolders, parseUuidOrSlugSelector8(commandOptions.to));
|
|
10898
11151
|
const data = await api.moveResource({
|
|
10899
11152
|
resourceId,
|
|
10900
11153
|
targetFolderId: resolved.id
|
|
@@ -10903,23 +11156,23 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
10903
11156
|
emitJson8(stdout, "navigation resources move", data, filePath);
|
|
10904
11157
|
return;
|
|
10905
11158
|
}
|
|
10906
|
-
|
|
11159
|
+
writeLine9(stdout, `Moved resource "${resourceId}" to "${resolved.name ?? resolved.id}".`);
|
|
10907
11160
|
});
|
|
10908
11161
|
}
|
|
10909
11162
|
|
|
10910
11163
|
// src/commands/profiles.ts
|
|
10911
|
-
function
|
|
11164
|
+
function getCommandIo10(stdout) {
|
|
10912
11165
|
return stdout ?? process.stdout;
|
|
10913
11166
|
}
|
|
10914
|
-
function
|
|
11167
|
+
function writeLine10(stdout, value) {
|
|
10915
11168
|
stdout.write(`${value}
|
|
10916
11169
|
`);
|
|
10917
11170
|
}
|
|
10918
|
-
function
|
|
11171
|
+
function getGlobalOptions10(command) {
|
|
10919
11172
|
return command.optsWithGlobals();
|
|
10920
11173
|
}
|
|
10921
11174
|
function emitJson9(stdout, commandName, data, configPath) {
|
|
10922
|
-
|
|
11175
|
+
writeLine10(
|
|
10923
11176
|
stdout,
|
|
10924
11177
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
10925
11178
|
);
|
|
@@ -10975,14 +11228,14 @@ function emitProfilesTable(stdout, data) {
|
|
|
10975
11228
|
}
|
|
10976
11229
|
function registerProfilesCommands(program, options = {}) {
|
|
10977
11230
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
10978
|
-
const stdout =
|
|
11231
|
+
const stdout = getCommandIo10(options.stdout);
|
|
10979
11232
|
const profiles = program.command("profiles").description("Manage local CLI profiles");
|
|
10980
11233
|
profiles.command("list").description("List configured profiles").action(function action() {
|
|
10981
11234
|
const config = readRequiredConfig(filePath);
|
|
10982
11235
|
const data = Object.entries(config.profiles).map(
|
|
10983
11236
|
([name, profile]) => toDisplayProfile(name, profile, config.defaultProfile)
|
|
10984
11237
|
);
|
|
10985
|
-
if (
|
|
11238
|
+
if (getGlobalOptions10(this).json) {
|
|
10986
11239
|
emitJson9(stdout, "profiles list", data, filePath);
|
|
10987
11240
|
return;
|
|
10988
11241
|
}
|
|
@@ -10992,7 +11245,7 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
10992
11245
|
const config = readRequiredConfig(filePath);
|
|
10993
11246
|
const profile = getRequiredProfile(config, profileName);
|
|
10994
11247
|
const data = toDisplayProfile(profileName, profile, config.defaultProfile);
|
|
10995
|
-
if (
|
|
11248
|
+
if (getGlobalOptions10(this).json) {
|
|
10996
11249
|
emitJson9(stdout, "profiles get", data, filePath);
|
|
10997
11250
|
return;
|
|
10998
11251
|
}
|
|
@@ -11007,11 +11260,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
11007
11260
|
profile: profileName,
|
|
11008
11261
|
defaultProfile: nextConfig.defaultProfile
|
|
11009
11262
|
};
|
|
11010
|
-
if (
|
|
11263
|
+
if (getGlobalOptions10(this).json) {
|
|
11011
11264
|
emitJson9(stdout, "profiles use", data, filePath);
|
|
11012
11265
|
return;
|
|
11013
11266
|
}
|
|
11014
|
-
|
|
11267
|
+
writeLine10(stdout, `Using profile "${profileName}".`);
|
|
11015
11268
|
});
|
|
11016
11269
|
profiles.command("add").description("Add a profile to the local config").argument("<profile>", "profile name").requiredOption("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
|
|
11017
11270
|
const config = loadConfigForAdd(filePath);
|
|
@@ -11035,11 +11288,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
11035
11288
|
nextConfig.profiles[profileName] ?? {},
|
|
11036
11289
|
nextConfig.defaultProfile
|
|
11037
11290
|
);
|
|
11038
|
-
if (
|
|
11291
|
+
if (getGlobalOptions10(this).json) {
|
|
11039
11292
|
emitJson9(stdout, "profiles add", data, filePath);
|
|
11040
11293
|
return;
|
|
11041
11294
|
}
|
|
11042
|
-
|
|
11295
|
+
writeLine10(stdout, `Added profile "${profileName}".`);
|
|
11043
11296
|
});
|
|
11044
11297
|
profiles.command("update").description("Update an existing profile").argument("<profile>", "profile name").option("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
|
|
11045
11298
|
if (commandOptions.apiKey === void 0 && commandOptions.baseUrl === void 0) {
|
|
@@ -11061,11 +11314,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
11061
11314
|
nextConfig.profiles[profileName] ?? {},
|
|
11062
11315
|
nextConfig.defaultProfile
|
|
11063
11316
|
);
|
|
11064
|
-
if (
|
|
11317
|
+
if (getGlobalOptions10(this).json) {
|
|
11065
11318
|
emitJson9(stdout, "profiles update", data, filePath);
|
|
11066
11319
|
return;
|
|
11067
11320
|
}
|
|
11068
|
-
|
|
11321
|
+
writeLine10(stdout, `Updated profile "${profileName}".`);
|
|
11069
11322
|
});
|
|
11070
11323
|
profiles.command("remove").description("Remove a profile from the local config").argument("<profile>", "profile name").action(function action(profileName) {
|
|
11071
11324
|
const config = readRequiredConfig(filePath);
|
|
@@ -11076,17 +11329,17 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
11076
11329
|
profile: profileName,
|
|
11077
11330
|
defaultProfile: nextConfig.defaultProfile
|
|
11078
11331
|
};
|
|
11079
|
-
if (
|
|
11332
|
+
if (getGlobalOptions10(this).json) {
|
|
11080
11333
|
emitJson9(stdout, "profiles remove", data, filePath);
|
|
11081
11334
|
return;
|
|
11082
11335
|
}
|
|
11083
|
-
|
|
11336
|
+
writeLine10(stdout, `Removed profile "${profileName}".`);
|
|
11084
11337
|
});
|
|
11085
11338
|
}
|
|
11086
11339
|
|
|
11087
11340
|
// src/commands/records.ts
|
|
11088
11341
|
import { readFileSync as readFileSync8 } from "fs";
|
|
11089
|
-
import { InvalidArgumentError as
|
|
11342
|
+
import { InvalidArgumentError as InvalidArgumentError9 } from "commander";
|
|
11090
11343
|
|
|
11091
11344
|
// src/api/records.ts
|
|
11092
11345
|
function jsonOptions6(body, method) {
|
|
@@ -11098,7 +11351,7 @@ function jsonOptions6(body, method) {
|
|
|
11098
11351
|
body: JSON.stringify(body)
|
|
11099
11352
|
};
|
|
11100
11353
|
}
|
|
11101
|
-
function
|
|
11354
|
+
function selectorValue9(selector) {
|
|
11102
11355
|
return selector.value;
|
|
11103
11356
|
}
|
|
11104
11357
|
var RecordsApi = class {
|
|
@@ -11113,7 +11366,7 @@ var RecordsApi = class {
|
|
|
11113
11366
|
if (query.offset !== void 0) {
|
|
11114
11367
|
params.set("offset", String(query.offset));
|
|
11115
11368
|
}
|
|
11116
|
-
const path = `/api/v2/schemas/${
|
|
11369
|
+
const path = `/api/v2/schemas/${selectorValue9(schema)}/records`;
|
|
11117
11370
|
const queryString = params.toString();
|
|
11118
11371
|
return this.client.getJson(
|
|
11119
11372
|
queryString ? `${path}?${queryString}` : path
|
|
@@ -11122,36 +11375,36 @@ var RecordsApi = class {
|
|
|
11122
11375
|
queryRecords(schema, query) {
|
|
11123
11376
|
const body = this.normalizeQueryInput(query);
|
|
11124
11377
|
return this.client.requestJson(
|
|
11125
|
-
`/api/v2/schemas/${
|
|
11378
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records:query`,
|
|
11126
11379
|
jsonOptions6(body, "POST")
|
|
11127
11380
|
);
|
|
11128
11381
|
}
|
|
11129
11382
|
getRecord(schema, record) {
|
|
11130
11383
|
return this.client.getJson(
|
|
11131
|
-
`/api/v2/schemas/${
|
|
11384
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records/${selectorValue9(record)}`
|
|
11132
11385
|
);
|
|
11133
11386
|
}
|
|
11134
11387
|
createRecords(schema, records) {
|
|
11135
11388
|
return this.client.requestJson(
|
|
11136
|
-
`/api/v2/schemas/${
|
|
11389
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records`,
|
|
11137
11390
|
jsonOptions6({ records }, "POST")
|
|
11138
11391
|
);
|
|
11139
11392
|
}
|
|
11140
11393
|
updateRecord(schema, record, input) {
|
|
11141
11394
|
return this.client.requestJson(
|
|
11142
|
-
`/api/v2/schemas/${
|
|
11395
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records/${selectorValue9(record)}`,
|
|
11143
11396
|
jsonOptions6(input, "PATCH")
|
|
11144
11397
|
);
|
|
11145
11398
|
}
|
|
11146
11399
|
deleteRecords(schema, recordIds) {
|
|
11147
11400
|
return this.client.requestJson(
|
|
11148
|
-
`/api/v2/schemas/${
|
|
11401
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records:delete`,
|
|
11149
11402
|
jsonOptions6({ recordIds }, "POST")
|
|
11150
11403
|
);
|
|
11151
11404
|
}
|
|
11152
11405
|
clearRecords(schema) {
|
|
11153
11406
|
return this.client.requestJson(
|
|
11154
|
-
`/api/v2/schemas/${
|
|
11407
|
+
`/api/v2/schemas/${selectorValue9(schema)}/records:clear`,
|
|
11155
11408
|
{ method: "DELETE" }
|
|
11156
11409
|
);
|
|
11157
11410
|
}
|
|
@@ -11193,7 +11446,7 @@ function jsonOptions7(body, method) {
|
|
|
11193
11446
|
body: JSON.stringify(body)
|
|
11194
11447
|
};
|
|
11195
11448
|
}
|
|
11196
|
-
function
|
|
11449
|
+
function selectorValue10(selector) {
|
|
11197
11450
|
return selector.value;
|
|
11198
11451
|
}
|
|
11199
11452
|
var SchemasApi = class {
|
|
@@ -11204,26 +11457,26 @@ var SchemasApi = class {
|
|
|
11204
11457
|
return this.client.getJson("/api/v2/schemas");
|
|
11205
11458
|
}
|
|
11206
11459
|
getSchema(schema) {
|
|
11207
|
-
return this.client.getJson(`/api/v2/schemas/${
|
|
11460
|
+
return this.client.getJson(`/api/v2/schemas/${selectorValue10(schema)}`);
|
|
11208
11461
|
}
|
|
11209
11462
|
createSchema(input) {
|
|
11210
11463
|
return this.client.requestJson("/api/v2/schemas", jsonOptions7(input, "POST"));
|
|
11211
11464
|
}
|
|
11212
11465
|
updateSchema(schema, input) {
|
|
11213
11466
|
return this.client.requestJson(
|
|
11214
|
-
`/api/v2/schemas/${
|
|
11467
|
+
`/api/v2/schemas/${selectorValue10(schema)}`,
|
|
11215
11468
|
jsonOptions7(input, "PATCH")
|
|
11216
11469
|
);
|
|
11217
11470
|
}
|
|
11218
11471
|
setUniqueFields(schema, input) {
|
|
11219
11472
|
return this.client.requestJson(
|
|
11220
|
-
`/api/v2/schemas/${
|
|
11473
|
+
`/api/v2/schemas/${selectorValue10(schema)}/unique-fields`,
|
|
11221
11474
|
jsonOptions7(input, "PUT")
|
|
11222
11475
|
);
|
|
11223
11476
|
}
|
|
11224
11477
|
deleteSchema(schema) {
|
|
11225
11478
|
return this.client.requestJson(
|
|
11226
|
-
`/api/v2/schemas/${
|
|
11479
|
+
`/api/v2/schemas/${selectorValue10(schema)}`,
|
|
11227
11480
|
{ method: "DELETE" }
|
|
11228
11481
|
);
|
|
11229
11482
|
}
|
|
@@ -11233,47 +11486,47 @@ var SchemasApi = class {
|
|
|
11233
11486
|
}
|
|
11234
11487
|
getField(schema, field) {
|
|
11235
11488
|
return this.client.getJson(
|
|
11236
|
-
`/api/v2/schemas/${
|
|
11489
|
+
`/api/v2/schemas/${selectorValue10(schema)}/fields/${selectorValue10(field)}`
|
|
11237
11490
|
);
|
|
11238
11491
|
}
|
|
11239
11492
|
createField(schema, input) {
|
|
11240
11493
|
return this.client.requestJson(
|
|
11241
|
-
`/api/v2/schemas/${
|
|
11494
|
+
`/api/v2/schemas/${selectorValue10(schema)}/fields`,
|
|
11242
11495
|
jsonOptions7(input, "POST")
|
|
11243
11496
|
);
|
|
11244
11497
|
}
|
|
11245
11498
|
updateField(schema, field, input) {
|
|
11246
11499
|
return this.client.requestJson(
|
|
11247
|
-
`/api/v2/schemas/${
|
|
11500
|
+
`/api/v2/schemas/${selectorValue10(schema)}/fields/${selectorValue10(field)}`,
|
|
11248
11501
|
jsonOptions7(input, "PATCH")
|
|
11249
11502
|
);
|
|
11250
11503
|
}
|
|
11251
11504
|
deleteField(schema, field) {
|
|
11252
11505
|
return this.client.requestJson(
|
|
11253
|
-
`/api/v2/schemas/${
|
|
11506
|
+
`/api/v2/schemas/${selectorValue10(schema)}/fields/${selectorValue10(field)}`,
|
|
11254
11507
|
{ method: "DELETE" }
|
|
11255
11508
|
);
|
|
11256
11509
|
}
|
|
11257
11510
|
};
|
|
11258
11511
|
|
|
11259
11512
|
// src/commands/records.ts
|
|
11260
|
-
function
|
|
11513
|
+
function getCommandIo11(stdout) {
|
|
11261
11514
|
return stdout ?? process.stdout;
|
|
11262
11515
|
}
|
|
11263
|
-
function
|
|
11516
|
+
function writeLine11(stdout, value) {
|
|
11264
11517
|
stdout.write(`${value}
|
|
11265
11518
|
`);
|
|
11266
11519
|
}
|
|
11267
|
-
function
|
|
11520
|
+
function getGlobalOptions11(command) {
|
|
11268
11521
|
return command.optsWithGlobals();
|
|
11269
11522
|
}
|
|
11270
11523
|
function emitJson10(stdout, commandName, data, configPath, meta = {}) {
|
|
11271
|
-
|
|
11524
|
+
writeLine11(
|
|
11272
11525
|
stdout,
|
|
11273
11526
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath, ...meta }))
|
|
11274
11527
|
);
|
|
11275
11528
|
}
|
|
11276
|
-
function
|
|
11529
|
+
function toConfigurationError10(filePath, error) {
|
|
11277
11530
|
if (error instanceof CliError) {
|
|
11278
11531
|
throw error;
|
|
11279
11532
|
}
|
|
@@ -11288,7 +11541,7 @@ function toConfigurationError9(filePath, error) {
|
|
|
11288
11541
|
function createRecordsApi(command, filePath) {
|
|
11289
11542
|
try {
|
|
11290
11543
|
const config = readRuntimeConfig(filePath);
|
|
11291
|
-
const runtime = resolveRuntimeContext(config,
|
|
11544
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions11(command));
|
|
11292
11545
|
if (!runtime.baseUrl) {
|
|
11293
11546
|
throw new CliError(
|
|
11294
11547
|
"configuration_error",
|
|
@@ -11307,10 +11560,10 @@ function createRecordsApi(command, filePath) {
|
|
|
11307
11560
|
readOnly: runtime.readOnly
|
|
11308
11561
|
};
|
|
11309
11562
|
} catch (error) {
|
|
11310
|
-
|
|
11563
|
+
toConfigurationError10(filePath, error);
|
|
11311
11564
|
}
|
|
11312
11565
|
}
|
|
11313
|
-
function
|
|
11566
|
+
function ensureWritable8(commandName, readOnly, commandMode) {
|
|
11314
11567
|
if (readOnly) {
|
|
11315
11568
|
throw new CliError(
|
|
11316
11569
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -11322,24 +11575,24 @@ function ensureWritable7(commandName, readOnly, commandMode) {
|
|
|
11322
11575
|
);
|
|
11323
11576
|
}
|
|
11324
11577
|
}
|
|
11325
|
-
function
|
|
11578
|
+
function parseUuidOrSlugSelector9(input) {
|
|
11326
11579
|
try {
|
|
11327
11580
|
return normalizeUuidOrSlug(input);
|
|
11328
11581
|
} catch (error) {
|
|
11329
11582
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
11330
|
-
throw new
|
|
11583
|
+
throw new InvalidArgumentError9(message);
|
|
11331
11584
|
}
|
|
11332
11585
|
}
|
|
11333
11586
|
function parseNonNegativeInteger2(input) {
|
|
11334
11587
|
if (!/^\d+$/.test(input.trim())) {
|
|
11335
|
-
throw new
|
|
11588
|
+
throw new InvalidArgumentError9(`Expected a non-negative integer, received "${input}".`);
|
|
11336
11589
|
}
|
|
11337
11590
|
return Number(input);
|
|
11338
11591
|
}
|
|
11339
11592
|
function parseCommaSeparatedValues(input, label) {
|
|
11340
11593
|
const values = input.split(",").map((value) => value.trim()).filter(Boolean);
|
|
11341
11594
|
if (values.length === 0) {
|
|
11342
|
-
throw new
|
|
11595
|
+
throw new InvalidArgumentError9(`Expected ${label} to contain at least one value.`);
|
|
11343
11596
|
}
|
|
11344
11597
|
return values;
|
|
11345
11598
|
}
|
|
@@ -11348,7 +11601,7 @@ function parseExpressionValue(input) {
|
|
|
11348
11601
|
return parseExpression(input);
|
|
11349
11602
|
} catch (error) {
|
|
11350
11603
|
const message = error instanceof Error ? error.message : "Invalid expression.";
|
|
11351
|
-
throw new
|
|
11604
|
+
throw new InvalidArgumentError9(message);
|
|
11352
11605
|
}
|
|
11353
11606
|
}
|
|
11354
11607
|
function parseKeyValueAssignment(input) {
|
|
@@ -11356,7 +11609,7 @@ function parseKeyValueAssignment(input) {
|
|
|
11356
11609
|
return parseKeyValue(input);
|
|
11357
11610
|
} catch (error) {
|
|
11358
11611
|
const message = error instanceof Error ? error.message : "Invalid assignment.";
|
|
11359
|
-
throw new
|
|
11612
|
+
throw new InvalidArgumentError9(message);
|
|
11360
11613
|
}
|
|
11361
11614
|
}
|
|
11362
11615
|
function parseJsonKeyValueAssignment(input) {
|
|
@@ -11364,7 +11617,7 @@ function parseJsonKeyValueAssignment(input) {
|
|
|
11364
11617
|
return parseJsonAssignment(input);
|
|
11365
11618
|
} catch (error) {
|
|
11366
11619
|
const message = error instanceof Error ? error.message : "Invalid JSON assignment.";
|
|
11367
|
-
throw new
|
|
11620
|
+
throw new InvalidArgumentError9(message);
|
|
11368
11621
|
}
|
|
11369
11622
|
}
|
|
11370
11623
|
function dedupeStrings(values) {
|
|
@@ -11381,7 +11634,7 @@ function toRecordUuid(value) {
|
|
|
11381
11634
|
function collectRecordIds(value, previous = []) {
|
|
11382
11635
|
const uuid = toRecordUuid(value.trim());
|
|
11383
11636
|
if (!uuid) {
|
|
11384
|
-
throw new
|
|
11637
|
+
throw new InvalidArgumentError9(`Expected a record UUID, received "${value}".`);
|
|
11385
11638
|
}
|
|
11386
11639
|
return [...previous, uuid];
|
|
11387
11640
|
}
|
|
@@ -11668,9 +11921,9 @@ async function resolveSchemaSelector(api, selector) {
|
|
|
11668
11921
|
}
|
|
11669
11922
|
function registerRecordsCommands(program, options = {}) {
|
|
11670
11923
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
11671
|
-
const stdout =
|
|
11924
|
+
const stdout = getCommandIo11(options.stdout);
|
|
11672
11925
|
const records = program.command("records").description("Manage schema records");
|
|
11673
|
-
records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug",
|
|
11926
|
+
records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).action(async function action(schema, commandOptions) {
|
|
11674
11927
|
const { api, schemasApi, json } = createRecordsApi(this, filePath);
|
|
11675
11928
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11676
11929
|
const data = await api.listRecords(
|
|
@@ -11690,7 +11943,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11690
11943
|
}
|
|
11691
11944
|
emitTable4(stdout, recordsData);
|
|
11692
11945
|
});
|
|
11693
|
-
records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug",
|
|
11946
|
+
records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option("--select <fields>", "field selection (comma-separated, repeatable)", collectSelectValues, []).option("--where <expression>", "where expression", collectWhereExpressions, []).option(
|
|
11694
11947
|
"--search <term>",
|
|
11695
11948
|
"free-text search term (matched across the schema's searchable fields)"
|
|
11696
11949
|
).option("--sort <field:direction>", "sort field(s)", collectSortValues, []).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
|
|
@@ -11713,7 +11966,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11713
11966
|
}
|
|
11714
11967
|
emitTable4(stdout, recordsData);
|
|
11715
11968
|
});
|
|
11716
|
-
records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
11969
|
+
records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema, record) {
|
|
11717
11970
|
const { api, schemasApi, json } = createRecordsApi(this, filePath);
|
|
11718
11971
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11719
11972
|
const data = await api.getRecord(resolvedSchema, record);
|
|
@@ -11723,7 +11976,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11723
11976
|
}
|
|
11724
11977
|
emitTable4(stdout, data);
|
|
11725
11978
|
});
|
|
11726
|
-
records.command("create").description("Create one or more records").argument("<schema>", "schema uuid or slug",
|
|
11979
|
+
records.command("create").description("Create one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option(
|
|
11727
11980
|
"--set <field=value>",
|
|
11728
11981
|
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11729
11982
|
collectKeyValueAssignments,
|
|
@@ -11733,7 +11986,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11733
11986
|
"path to a JSON array of record objects (mutually exclusive with --set/--set-json/--raw/--raw-file)"
|
|
11734
11987
|
).action(async function action(schema, commandOptions) {
|
|
11735
11988
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11736
|
-
|
|
11989
|
+
ensureWritable8("records create", readOnly, "write");
|
|
11737
11990
|
const records2 = buildCreateRecords(commandOptions);
|
|
11738
11991
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11739
11992
|
const data = await api.createRecords(resolvedSchema, records2);
|
|
@@ -11741,22 +11994,22 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11741
11994
|
emitJson10(stdout, "records create", data, filePath);
|
|
11742
11995
|
return;
|
|
11743
11996
|
}
|
|
11744
|
-
|
|
11997
|
+
writeLine11(stdout, `Created ${data.created.length} record(s) in schema "${schema.value}".`);
|
|
11745
11998
|
if (data.errors.length > 0) {
|
|
11746
|
-
|
|
11999
|
+
writeLine11(stdout, `${data.errors.length} record(s) rejected:`);
|
|
11747
12000
|
for (const error of data.errors) {
|
|
11748
|
-
|
|
12001
|
+
writeLine11(stdout, ` - index ${error.index}: ${error.message}`);
|
|
11749
12002
|
}
|
|
11750
12003
|
}
|
|
11751
12004
|
});
|
|
11752
|
-
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug",
|
|
12005
|
+
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector9).option(
|
|
11753
12006
|
"--set <field=value>",
|
|
11754
12007
|
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11755
12008
|
collectKeyValueAssignments,
|
|
11756
12009
|
[]
|
|
11757
12010
|
).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--unset <field>", "unset a field", collectStringValues, []).option("--raw <json>", "raw JSON object of fields to set").option("--raw-file <path>", "path to a JSON object of fields to set").action(async function action(schema, record, commandOptions) {
|
|
11758
12011
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11759
|
-
|
|
12012
|
+
ensureWritable8("records update", readOnly, "write");
|
|
11760
12013
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11761
12014
|
const data = await api.updateRecord(
|
|
11762
12015
|
resolvedSchema,
|
|
@@ -11767,14 +12020,14 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11767
12020
|
emitJson10(stdout, "records update", data, filePath);
|
|
11768
12021
|
return;
|
|
11769
12022
|
}
|
|
11770
|
-
|
|
12023
|
+
writeLine11(stdout, `Updated record "${getRecordIdentifier(data)}".`);
|
|
11771
12024
|
});
|
|
11772
|
-
records.command("delete").description("Delete one or more records").argument("<schema>", "schema uuid or slug",
|
|
12025
|
+
records.command("delete").description("Delete one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option("--record <uuid>", "record uuid to delete (repeatable)", collectRecordIds, []).option(
|
|
11773
12026
|
"--records-file <path>",
|
|
11774
12027
|
"path to a file with one record uuid per line (merged with --record)"
|
|
11775
12028
|
).action(async function action(schema, commandOptions) {
|
|
11776
12029
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11777
|
-
|
|
12030
|
+
ensureWritable8("records delete", readOnly, "destructive");
|
|
11778
12031
|
const recordIds = resolveDeleteRecordIds(commandOptions);
|
|
11779
12032
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11780
12033
|
const data = await api.deleteRecords(resolvedSchema, recordIds);
|
|
@@ -11782,27 +12035,27 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
11782
12035
|
emitJson10(stdout, "records delete", data, filePath);
|
|
11783
12036
|
return;
|
|
11784
12037
|
}
|
|
11785
|
-
|
|
12038
|
+
writeLine11(
|
|
11786
12039
|
stdout,
|
|
11787
12040
|
`Deleted ${recordIds.length} record(s) from schema "${schema.value}".`
|
|
11788
12041
|
);
|
|
11789
12042
|
});
|
|
11790
|
-
records.command("clear").description("Delete all records from a schema's table").argument("<schema>", "schema uuid or slug",
|
|
12043
|
+
records.command("clear").description("Delete all records from a schema's table").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema) {
|
|
11791
12044
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
11792
|
-
|
|
12045
|
+
ensureWritable8("records clear", readOnly, "destructive");
|
|
11793
12046
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
11794
12047
|
const data = await api.clearRecords(resolvedSchema);
|
|
11795
12048
|
if (json) {
|
|
11796
12049
|
emitJson10(stdout, "records clear", data, filePath);
|
|
11797
12050
|
return;
|
|
11798
12051
|
}
|
|
11799
|
-
|
|
12052
|
+
writeLine11(stdout, `Cleared all records from schema "${schema.value}".`);
|
|
11800
12053
|
});
|
|
11801
12054
|
}
|
|
11802
12055
|
|
|
11803
12056
|
// src/commands/schemas.ts
|
|
11804
12057
|
import { readFileSync as readFileSync9 } from "fs";
|
|
11805
|
-
import { InvalidArgumentError as
|
|
12058
|
+
import { InvalidArgumentError as InvalidArgumentError10 } from "commander";
|
|
11806
12059
|
var HIGHLIGHTED_FIELD_HELP = `
|
|
11807
12060
|
Highlighted field:
|
|
11808
12061
|
The schema's "main" field. The frontend uses its value as each record's
|
|
@@ -11812,23 +12065,23 @@ Highlighted field:
|
|
|
11812
12065
|
- Detail view: the record's name in the left-hand record list you
|
|
11813
12066
|
browse to open each record's form.
|
|
11814
12067
|
`;
|
|
11815
|
-
function
|
|
12068
|
+
function getCommandIo12(stdout) {
|
|
11816
12069
|
return stdout ?? process.stdout;
|
|
11817
12070
|
}
|
|
11818
|
-
function
|
|
12071
|
+
function writeLine12(stdout, value) {
|
|
11819
12072
|
stdout.write(`${value}
|
|
11820
12073
|
`);
|
|
11821
12074
|
}
|
|
11822
|
-
function
|
|
12075
|
+
function getGlobalOptions12(command) {
|
|
11823
12076
|
return command.optsWithGlobals();
|
|
11824
12077
|
}
|
|
11825
12078
|
function emitJson11(stdout, commandName, data, configPath) {
|
|
11826
|
-
|
|
12079
|
+
writeLine12(
|
|
11827
12080
|
stdout,
|
|
11828
12081
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
11829
12082
|
);
|
|
11830
12083
|
}
|
|
11831
|
-
function
|
|
12084
|
+
function toConfigurationError11(filePath, error) {
|
|
11832
12085
|
if (error instanceof CliError) {
|
|
11833
12086
|
throw error;
|
|
11834
12087
|
}
|
|
@@ -11843,7 +12096,7 @@ function toConfigurationError10(filePath, error) {
|
|
|
11843
12096
|
function createSchemasApi(command, filePath) {
|
|
11844
12097
|
try {
|
|
11845
12098
|
const config = readRuntimeConfig(filePath);
|
|
11846
|
-
const runtime = resolveRuntimeContext(config,
|
|
12099
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions12(command));
|
|
11847
12100
|
if (!runtime.baseUrl) {
|
|
11848
12101
|
throw new CliError(
|
|
11849
12102
|
"configuration_error",
|
|
@@ -11862,10 +12115,10 @@ function createSchemasApi(command, filePath) {
|
|
|
11862
12115
|
readOnly: runtime.readOnly
|
|
11863
12116
|
};
|
|
11864
12117
|
} catch (error) {
|
|
11865
|
-
|
|
12118
|
+
toConfigurationError11(filePath, error);
|
|
11866
12119
|
}
|
|
11867
12120
|
}
|
|
11868
|
-
function
|
|
12121
|
+
function ensureWritable9(commandName, readOnly, commandMode) {
|
|
11869
12122
|
if (readOnly) {
|
|
11870
12123
|
throw new CliError(
|
|
11871
12124
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -11877,16 +12130,16 @@ function ensureWritable8(commandName, readOnly, commandMode) {
|
|
|
11877
12130
|
);
|
|
11878
12131
|
}
|
|
11879
12132
|
}
|
|
11880
|
-
function
|
|
12133
|
+
function parseUuidOrSlugSelector10(input) {
|
|
11881
12134
|
try {
|
|
11882
12135
|
return normalizeUuidOrSlug(input);
|
|
11883
12136
|
} catch (error) {
|
|
11884
12137
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
11885
|
-
throw new
|
|
12138
|
+
throw new InvalidArgumentError10(message);
|
|
11886
12139
|
}
|
|
11887
12140
|
}
|
|
11888
12141
|
function collectFieldSelectors(value, previous = []) {
|
|
11889
|
-
return [...previous,
|
|
12142
|
+
return [...previous, parseUuidOrSlugSelector10(value)];
|
|
11890
12143
|
}
|
|
11891
12144
|
function parseBooleanFlag(input) {
|
|
11892
12145
|
const normalized = input.trim().toLowerCase();
|
|
@@ -11896,7 +12149,7 @@ function parseBooleanFlag(input) {
|
|
|
11896
12149
|
if (["false", "0", "no", "n", "off"].includes(normalized)) {
|
|
11897
12150
|
return false;
|
|
11898
12151
|
}
|
|
11899
|
-
throw new
|
|
12152
|
+
throw new InvalidArgumentError10(`Expected a boolean value, received "${input}".`);
|
|
11900
12153
|
}
|
|
11901
12154
|
function isJsonObject7(value) {
|
|
11902
12155
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -12111,7 +12364,7 @@ function isEmptyObject6(value) {
|
|
|
12111
12364
|
}
|
|
12112
12365
|
function registerSchemasCommands(program, options = {}) {
|
|
12113
12366
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
12114
|
-
const stdout =
|
|
12367
|
+
const stdout = getCommandIo12(options.stdout);
|
|
12115
12368
|
const schemas = program.command("schemas").description("Manage schemas and schema fields");
|
|
12116
12369
|
schemas.command("list").description("List schemas").action(async function action() {
|
|
12117
12370
|
const { api, json } = createSchemasApi(this, filePath);
|
|
@@ -12122,7 +12375,7 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12122
12375
|
}
|
|
12123
12376
|
emitSchemasTable(stdout, data);
|
|
12124
12377
|
});
|
|
12125
|
-
schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
12378
|
+
schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).action(async function action(schema) {
|
|
12126
12379
|
const { api, json } = createSchemasApi(this, filePath);
|
|
12127
12380
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12128
12381
|
const data = await api.getSchema(resolvedSchema);
|
|
@@ -12134,7 +12387,7 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12134
12387
|
});
|
|
12135
12388
|
schemas.command("create").description("Create a schema").requiredOption("--name <name>", "schema name").requiredOption("--slug <slug>", "schema slug").option("--auditable", "mark schema as auditable").option("--commentable", "mark schema as commentable").action(async function action(commandOptions) {
|
|
12136
12389
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12137
|
-
|
|
12390
|
+
ensureWritable9("schemas create", readOnly, "write");
|
|
12138
12391
|
const input = {
|
|
12139
12392
|
name: commandOptions.name,
|
|
12140
12393
|
slug: commandOptions.slug,
|
|
@@ -12146,15 +12399,15 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12146
12399
|
emitJson11(stdout, "schemas create", data, filePath);
|
|
12147
12400
|
return;
|
|
12148
12401
|
}
|
|
12149
|
-
|
|
12402
|
+
writeLine12(stdout, `Created schema "${data.slug ?? commandOptions.slug}".`);
|
|
12150
12403
|
});
|
|
12151
|
-
schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug",
|
|
12404
|
+
schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).option("--name <name>", "schema name").option("--slug <slug>", "schema slug").option("--auditable <bool>", "auditable flag", parseBooleanFlag).option("--commentable <bool>", "commentable flag", parseBooleanFlag).option(
|
|
12152
12405
|
"--highlighted-field <field>",
|
|
12153
12406
|
"its value is used as each record's display name in the UI (field uuid or slug)",
|
|
12154
|
-
|
|
12407
|
+
parseUuidOrSlugSelector10
|
|
12155
12408
|
).action(async function action(schema, commandOptions) {
|
|
12156
12409
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12157
|
-
|
|
12410
|
+
ensureWritable9("schemas update", readOnly, "write");
|
|
12158
12411
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12159
12412
|
const input = buildSchemaUpdateInput(commandOptions);
|
|
12160
12413
|
if (commandOptions.highlightedField !== void 0) {
|
|
@@ -12176,16 +12429,16 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12176
12429
|
emitJson11(stdout, "schemas update", data, filePath);
|
|
12177
12430
|
return;
|
|
12178
12431
|
}
|
|
12179
|
-
|
|
12432
|
+
writeLine12(stdout, `Updated schema "${data.slug ?? schema.value}".`);
|
|
12180
12433
|
}).addHelpText("after", HIGHLIGHTED_FIELD_HELP);
|
|
12181
|
-
schemas.command("set-unique-fields").description("Set or clear the composite unique-field constraint on a schema").argument("<schema>", "schema uuid or slug",
|
|
12434
|
+
schemas.command("set-unique-fields").description("Set or clear the composite unique-field constraint on a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).option(
|
|
12182
12435
|
"--field <field>",
|
|
12183
12436
|
"field uuid or slug to include in the unique constraint (repeatable)",
|
|
12184
12437
|
collectFieldSelectors,
|
|
12185
12438
|
[]
|
|
12186
12439
|
).option("--clear", "clear the unique constraint (sends an empty field list)").action(async function action(schema, commandOptions) {
|
|
12187
12440
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12188
|
-
|
|
12441
|
+
ensureWritable9("schemas set-unique-fields", readOnly, "write");
|
|
12189
12442
|
const selectors = commandOptions.field ?? [];
|
|
12190
12443
|
if (commandOptions.clear && selectors.length > 0) {
|
|
12191
12444
|
throw new CliError(
|
|
@@ -12212,18 +12465,18 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12212
12465
|
return;
|
|
12213
12466
|
}
|
|
12214
12467
|
if (input.fieldIds.length === 0) {
|
|
12215
|
-
|
|
12468
|
+
writeLine12(stdout, `Cleared unique fields on schema "${schema.value}".`);
|
|
12216
12469
|
return;
|
|
12217
12470
|
}
|
|
12218
12471
|
const count = input.fieldIds.length;
|
|
12219
|
-
|
|
12472
|
+
writeLine12(
|
|
12220
12473
|
stdout,
|
|
12221
12474
|
`Set unique fields on schema "${schema.value}" (${count} field${count === 1 ? "" : "s"}).`
|
|
12222
12475
|
);
|
|
12223
12476
|
});
|
|
12224
|
-
schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug",
|
|
12477
|
+
schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).action(async function action(schema) {
|
|
12225
12478
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12226
|
-
|
|
12479
|
+
ensureWritable9("schemas delete", readOnly, "destructive");
|
|
12227
12480
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12228
12481
|
await api.deleteSchema(resolvedSchema);
|
|
12229
12482
|
const data = {
|
|
@@ -12234,10 +12487,10 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12234
12487
|
emitJson11(stdout, "schemas delete", data, filePath);
|
|
12235
12488
|
return;
|
|
12236
12489
|
}
|
|
12237
|
-
|
|
12490
|
+
writeLine12(stdout, `Deleted schema "${schema.value}".`);
|
|
12238
12491
|
});
|
|
12239
12492
|
const fields = schemas.command("fields").description("Manage schema fields");
|
|
12240
|
-
fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug",
|
|
12493
|
+
fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).action(async function action(schema) {
|
|
12241
12494
|
const { api, json } = createSchemasApi(this, filePath);
|
|
12242
12495
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12243
12496
|
const data = await api.listFields(resolvedSchema);
|
|
@@ -12247,7 +12500,7 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12247
12500
|
}
|
|
12248
12501
|
emitFieldsTable(stdout, data);
|
|
12249
12502
|
});
|
|
12250
|
-
fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
12503
|
+
fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector10).action(async function action(schema, field) {
|
|
12251
12504
|
const { api, json } = createSchemasApi(this, filePath);
|
|
12252
12505
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12253
12506
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
@@ -12258,9 +12511,9 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12258
12511
|
}
|
|
12259
12512
|
emitFieldsTable(stdout, [data]);
|
|
12260
12513
|
});
|
|
12261
|
-
fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug",
|
|
12514
|
+
fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).option("--type <type>", `field type (${formatSchemaFieldTypes()})`).option("--slug <slug>", "field slug").option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--default <value>", "default field value").option("--raw <json>", "raw JSON object payload (see type-specific shapes in --help)").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
|
|
12262
12515
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12263
|
-
|
|
12516
|
+
ensureWritable9("schemas fields create", readOnly, "write");
|
|
12264
12517
|
const input = buildFieldCreateInput(commandOptions);
|
|
12265
12518
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12266
12519
|
let data;
|
|
@@ -12273,11 +12526,11 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12273
12526
|
emitJson11(stdout, "schemas fields create", data, filePath);
|
|
12274
12527
|
return;
|
|
12275
12528
|
}
|
|
12276
|
-
|
|
12529
|
+
writeLine12(stdout, `Created field "${data.slug ?? commandOptions.slug}".`);
|
|
12277
12530
|
});
|
|
12278
|
-
fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug",
|
|
12531
|
+
fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector10).option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--default <value>", "default field value").option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, field, commandOptions) {
|
|
12279
12532
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12280
|
-
|
|
12533
|
+
ensureWritable9("schemas fields update", readOnly, "write");
|
|
12281
12534
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12282
12535
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
12283
12536
|
const currentField = await api.getField(resolvedSchema, resolvedField);
|
|
@@ -12297,11 +12550,11 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12297
12550
|
emitJson11(stdout, "schemas fields update", data, filePath);
|
|
12298
12551
|
return;
|
|
12299
12552
|
}
|
|
12300
|
-
|
|
12553
|
+
writeLine12(stdout, `Updated field "${data.slug ?? field.value}".`);
|
|
12301
12554
|
});
|
|
12302
|
-
fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug",
|
|
12555
|
+
fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector10).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector10).action(async function action(schema, field) {
|
|
12303
12556
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
12304
|
-
|
|
12557
|
+
ensureWritable9("schemas fields delete", readOnly, "destructive");
|
|
12305
12558
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
12306
12559
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
12307
12560
|
await api.deleteField(resolvedSchema, resolvedField);
|
|
@@ -12314,13 +12567,13 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
12314
12567
|
emitJson11(stdout, "schemas fields delete", data, filePath);
|
|
12315
12568
|
return;
|
|
12316
12569
|
}
|
|
12317
|
-
|
|
12570
|
+
writeLine12(stdout, `Deleted field "${field.value}" from schema "${schema.value}".`);
|
|
12318
12571
|
});
|
|
12319
12572
|
}
|
|
12320
12573
|
|
|
12321
12574
|
// src/commands/teamspace.ts
|
|
12322
12575
|
import { readFileSync as readFileSync10 } from "fs";
|
|
12323
|
-
import { InvalidArgumentError as
|
|
12576
|
+
import { InvalidArgumentError as InvalidArgumentError11 } from "commander";
|
|
12324
12577
|
|
|
12325
12578
|
// src/api/teamspace.ts
|
|
12326
12579
|
function jsonOptions8(body, method) {
|
|
@@ -12332,7 +12585,7 @@ function jsonOptions8(body, method) {
|
|
|
12332
12585
|
body: JSON.stringify(body)
|
|
12333
12586
|
};
|
|
12334
12587
|
}
|
|
12335
|
-
function
|
|
12588
|
+
function selectorValue11(selector) {
|
|
12336
12589
|
return selector.value;
|
|
12337
12590
|
}
|
|
12338
12591
|
var TeamspaceApi = class {
|
|
@@ -12358,13 +12611,13 @@ var TeamspaceApi = class {
|
|
|
12358
12611
|
}
|
|
12359
12612
|
updateFolder(folder, input) {
|
|
12360
12613
|
return this.client.requestJson(
|
|
12361
|
-
`/api/v2/teamspaces/folders/${
|
|
12614
|
+
`/api/v2/teamspaces/folders/${selectorValue11(folder)}`,
|
|
12362
12615
|
jsonOptions8(input, "PATCH")
|
|
12363
12616
|
);
|
|
12364
12617
|
}
|
|
12365
12618
|
deleteFolder(folder) {
|
|
12366
12619
|
return this.client.requestJson(
|
|
12367
|
-
`/api/v2/teamspaces/folders/${
|
|
12620
|
+
`/api/v2/teamspaces/folders/${selectorValue11(folder)}`,
|
|
12368
12621
|
{ method: "DELETE" }
|
|
12369
12622
|
);
|
|
12370
12623
|
}
|
|
@@ -12383,23 +12636,23 @@ var TeamspaceApi = class {
|
|
|
12383
12636
|
};
|
|
12384
12637
|
|
|
12385
12638
|
// src/commands/teamspace.ts
|
|
12386
|
-
function
|
|
12639
|
+
function getCommandIo13(stdout) {
|
|
12387
12640
|
return stdout ?? process.stdout;
|
|
12388
12641
|
}
|
|
12389
|
-
function
|
|
12642
|
+
function writeLine13(stdout, value) {
|
|
12390
12643
|
stdout.write(`${value}
|
|
12391
12644
|
`);
|
|
12392
12645
|
}
|
|
12393
|
-
function
|
|
12646
|
+
function getGlobalOptions13(command) {
|
|
12394
12647
|
return command.optsWithGlobals();
|
|
12395
12648
|
}
|
|
12396
12649
|
function emitJson12(stdout, commandName, data, configPath) {
|
|
12397
|
-
|
|
12650
|
+
writeLine13(
|
|
12398
12651
|
stdout,
|
|
12399
12652
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
12400
12653
|
);
|
|
12401
12654
|
}
|
|
12402
|
-
function
|
|
12655
|
+
function toConfigurationError12(filePath, error) {
|
|
12403
12656
|
if (error instanceof CliError) {
|
|
12404
12657
|
throw error;
|
|
12405
12658
|
}
|
|
@@ -12414,7 +12667,7 @@ function toConfigurationError11(filePath, error) {
|
|
|
12414
12667
|
function createTeamspaceApi(command, filePath) {
|
|
12415
12668
|
try {
|
|
12416
12669
|
const config = readRuntimeConfig(filePath);
|
|
12417
|
-
const runtime = resolveRuntimeContext(config,
|
|
12670
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions13(command));
|
|
12418
12671
|
if (!runtime.baseUrl) {
|
|
12419
12672
|
throw new CliError(
|
|
12420
12673
|
"configuration_error",
|
|
@@ -12432,10 +12685,10 @@ function createTeamspaceApi(command, filePath) {
|
|
|
12432
12685
|
readOnly: runtime.readOnly
|
|
12433
12686
|
};
|
|
12434
12687
|
} catch (error) {
|
|
12435
|
-
|
|
12688
|
+
toConfigurationError12(filePath, error);
|
|
12436
12689
|
}
|
|
12437
12690
|
}
|
|
12438
|
-
function
|
|
12691
|
+
function ensureWritable10(commandName, readOnly, commandMode) {
|
|
12439
12692
|
if (readOnly) {
|
|
12440
12693
|
throw new CliError(
|
|
12441
12694
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -12447,17 +12700,17 @@ function ensureWritable9(commandName, readOnly, commandMode) {
|
|
|
12447
12700
|
);
|
|
12448
12701
|
}
|
|
12449
12702
|
}
|
|
12450
|
-
function
|
|
12703
|
+
function parseUuidOrSlugSelector11(input) {
|
|
12451
12704
|
try {
|
|
12452
12705
|
return normalizeUuidOrSlug(input);
|
|
12453
12706
|
} catch (error) {
|
|
12454
12707
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
12455
|
-
throw new
|
|
12708
|
+
throw new InvalidArgumentError11(message);
|
|
12456
12709
|
}
|
|
12457
12710
|
}
|
|
12458
12711
|
function parseNonNegativeInteger3(input) {
|
|
12459
12712
|
if (!/^\d+$/.test(input.trim())) {
|
|
12460
|
-
throw new
|
|
12713
|
+
throw new InvalidArgumentError11(`Expected a non-negative integer, received "${input}".`);
|
|
12461
12714
|
}
|
|
12462
12715
|
return Number(input);
|
|
12463
12716
|
}
|
|
@@ -12613,7 +12866,7 @@ async function resolveFolderSelector2(api, selector) {
|
|
|
12613
12866
|
}
|
|
12614
12867
|
function registerTeamspaceCommands(program, options = {}) {
|
|
12615
12868
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
12616
|
-
const stdout =
|
|
12869
|
+
const stdout = getCommandIo13(options.stdout);
|
|
12617
12870
|
const teamspace = program.command("teamspace").description("Manage teamspace folders and resources");
|
|
12618
12871
|
const folders = teamspace.command("folders").description("Manage teamspace folders");
|
|
12619
12872
|
folders.command("list").description("List teamspace folders").option("--include-resources", "include the published resources inside each folder").action(async function action(commandOptions) {
|
|
@@ -12625,7 +12878,7 @@ function registerTeamspaceCommands(program, options = {}) {
|
|
|
12625
12878
|
}
|
|
12626
12879
|
emitTable5(stdout, data);
|
|
12627
12880
|
});
|
|
12628
|
-
folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name",
|
|
12881
|
+
folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector11).option("--include-resources", "include the published resources inside each folder").action(async function action(folder, commandOptions) {
|
|
12629
12882
|
const { api, json } = createTeamspaceApi(this, filePath);
|
|
12630
12883
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
12631
12884
|
const allFolders = await api.listFolders(Boolean(commandOptions.includeResources));
|
|
@@ -12638,46 +12891,46 @@ function registerTeamspaceCommands(program, options = {}) {
|
|
|
12638
12891
|
});
|
|
12639
12892
|
folders.command("create").description("Create a teamspace folder").requiredOption("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)", parseNonNegativeInteger3).option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"icon":"folder-users","color":"gold"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(commandOptions) {
|
|
12640
12893
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
12641
|
-
|
|
12894
|
+
ensureWritable10("teamspace folders create", readOnly, "write");
|
|
12642
12895
|
const data = await api.createFolder(buildFolderCreateInput(commandOptions));
|
|
12643
12896
|
if (json) {
|
|
12644
12897
|
emitJson12(stdout, "teamspace folders create", data, filePath);
|
|
12645
12898
|
return;
|
|
12646
12899
|
}
|
|
12647
|
-
|
|
12900
|
+
writeLine13(stdout, `Created folder "${getFolderIdentifier(data)}".`);
|
|
12648
12901
|
});
|
|
12649
|
-
folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name",
|
|
12902
|
+
folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector11).option("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)", parseNonNegativeInteger3).option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"icon":"folder-users","color":"gold"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(folder, commandOptions) {
|
|
12650
12903
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
12651
|
-
|
|
12904
|
+
ensureWritable10("teamspace folders update", readOnly, "write");
|
|
12652
12905
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
12653
12906
|
const data = await api.updateFolder(resolvedFolder, buildFolderUpdateInput(commandOptions));
|
|
12654
12907
|
if (json) {
|
|
12655
12908
|
emitJson12(stdout, "teamspace folders update", data, filePath);
|
|
12656
12909
|
return;
|
|
12657
12910
|
}
|
|
12658
|
-
|
|
12911
|
+
writeLine13(stdout, `Updated folder "${getFolderIdentifier(data)}".`);
|
|
12659
12912
|
});
|
|
12660
|
-
folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name",
|
|
12913
|
+
folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector11).action(async function action(folder) {
|
|
12661
12914
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
12662
|
-
|
|
12915
|
+
ensureWritable10("teamspace folders delete", readOnly, "destructive");
|
|
12663
12916
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
12664
12917
|
const data = await api.deleteFolder(resolvedFolder);
|
|
12665
12918
|
if (json) {
|
|
12666
12919
|
emitJson12(stdout, "teamspace folders delete", data, filePath);
|
|
12667
12920
|
return;
|
|
12668
12921
|
}
|
|
12669
|
-
|
|
12922
|
+
writeLine13(stdout, `Deleted folder "${resolvedFolder.value}".`);
|
|
12670
12923
|
});
|
|
12671
12924
|
const resources = teamspace.command("resources").description("Manage teamspace resources");
|
|
12672
12925
|
resources.command("publish").description(
|
|
12673
12926
|
"Publish a resource to a teamspace folder. Publishing an already-published resource moves it to the new folder."
|
|
12674
|
-
).argument("<resource>", "schema UUID, schema slug, or display UUID",
|
|
12927
|
+
).argument("<resource>", "schema UUID, schema slug, or display UUID", parseUuidOrSlugSelector11).requiredOption(
|
|
12675
12928
|
"--to <folder>",
|
|
12676
12929
|
"target folder UUID or exact name (root folder UUID is 00000000-0000-0000-0000-000000000000)",
|
|
12677
|
-
|
|
12930
|
+
parseUuidOrSlugSelector11
|
|
12678
12931
|
).action(async function action(resource, commandOptions) {
|
|
12679
12932
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
12680
|
-
|
|
12933
|
+
ensureWritable10("teamspace resources publish", readOnly, "write");
|
|
12681
12934
|
const folder = await resolveFolderSelector2(api, commandOptions.to);
|
|
12682
12935
|
const data = await api.publishResource({
|
|
12683
12936
|
resourceId: resource.value,
|
|
@@ -12687,17 +12940,17 @@ function registerTeamspaceCommands(program, options = {}) {
|
|
|
12687
12940
|
emitJson12(stdout, "teamspace resources publish", data, filePath);
|
|
12688
12941
|
return;
|
|
12689
12942
|
}
|
|
12690
|
-
|
|
12943
|
+
writeLine13(stdout, `Published resource "${resource.value}" to folder "${folder.value}".`);
|
|
12691
12944
|
});
|
|
12692
|
-
resources.command("unpublish").description("Unpublish a resource from teamspace (removes it from its shared folder)").argument("<resource>", "schema UUID, schema slug, or display UUID",
|
|
12945
|
+
resources.command("unpublish").description("Unpublish a resource from teamspace (removes it from its shared folder)").argument("<resource>", "schema UUID, schema slug, or display UUID", parseUuidOrSlugSelector11).action(async function action(resource) {
|
|
12693
12946
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
12694
|
-
|
|
12947
|
+
ensureWritable10("teamspace resources unpublish", readOnly, "write");
|
|
12695
12948
|
const data = await api.unpublishResource(resource.value);
|
|
12696
12949
|
if (json) {
|
|
12697
12950
|
emitJson12(stdout, "teamspace resources unpublish", data, filePath);
|
|
12698
12951
|
return;
|
|
12699
12952
|
}
|
|
12700
|
-
|
|
12953
|
+
writeLine13(stdout, `Unpublished resource "${resource.value}".`);
|
|
12701
12954
|
});
|
|
12702
12955
|
}
|
|
12703
12956
|
|
|
@@ -12705,7 +12958,7 @@ function registerTeamspaceCommands(program, options = {}) {
|
|
|
12705
12958
|
var require2 = createRequire(import.meta.url);
|
|
12706
12959
|
var { version } = require2("../package.json");
|
|
12707
12960
|
function buildProgram(options = {}) {
|
|
12708
|
-
const program = new
|
|
12961
|
+
const program = new Command12();
|
|
12709
12962
|
program.name("zinkee").description("CLI for Zinkee API v2").version(version).enablePositionalOptions().showHelpAfterError().option("--profile <name>", "select a profile from config").option("--base-url <url>", "override the configured base URL").option("--api-key <token>", "override the configured API key").option("--read-only", "run in read-only mode").option("--example", "show examples for a command").option("--json", "emit JSON output").option("--install-completion [shell]", "install shell completion (bash, zsh, fish, powershell)").option("--show-completion [shell]", "print shell completion script for the current shell");
|
|
12710
12963
|
registerProfilesCommands(program, options);
|
|
12711
12964
|
registerAutomationsCommands(program, options);
|
|
@@ -12713,6 +12966,7 @@ function buildProgram(options = {}) {
|
|
|
12713
12966
|
registerDisplaysCommands(program, options);
|
|
12714
12967
|
registerDocumentTemplatesCommands(program, options);
|
|
12715
12968
|
registerFilesCommands(program, options);
|
|
12969
|
+
registerFormulasCommands(program, options);
|
|
12716
12970
|
registerNavigationCommands(program, options);
|
|
12717
12971
|
registerSchemasCommands(program, options);
|
|
12718
12972
|
registerRecordsCommands(program, options);
|