primitive-admin 1.1.0-alpha.44 → 1.1.0-alpha.46
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/primitive.js +2 -0
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/blob-buckets.js +20 -7
- package/dist/src/commands/blob-buckets.js.map +1 -1
- package/dist/src/commands/collections.js +11 -0
- package/dist/src/commands/collections.js.map +1 -1
- package/dist/src/commands/databases.js +34 -49
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/sync.js +116 -28
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/vars.d.ts +8 -0
- package/dist/src/commands/vars.js +110 -0
- package/dist/src/commands/vars.js.map +1 -0
- package/dist/src/commands/workflows.js +126 -20
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +10 -0
- package/dist/src/lib/api-client.js +19 -0
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +61 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js +127 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +68 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +168 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +30 -5
- package/dist/src/lib/db-codegen/dbGenerator.js +227 -165
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +11 -23
- package/dist/src/lib/db-codegen/dbTemplates.js +21 -41
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +7 -3
- package/dist/src/lib/db-codegen/dbTsTypes.js +23 -1
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -1
- package/dist/src/lib/generated-allowlist.js +15 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/toml-metadata-config.d.ts +10 -2
- package/dist/src/lib/toml-metadata-config.js +51 -15
- package/dist/src/lib/toml-metadata-config.js.map +1 -1
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.d.ts +129 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js +269 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generator.d.ts +74 -0
- package/dist/src/lib/workflow-codegen/generator.js +215 -0
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -0
- package/dist/src/lib/workflow-codegen/naming.d.ts +33 -0
- package/dist/src/lib/workflow-codegen/naming.js +81 -0
- package/dist/src/lib/workflow-codegen/naming.js.map +1 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +64 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js +282 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* `primitive vars` — non-secret per-app config scalars (issue #1364). The
|
|
4
|
+
* plaintext twin of `primitive secrets`: same key format and limits, but
|
|
5
|
+
* values are NOT secret — `list` shows them, and they appear unmasked in
|
|
6
|
+
* debug traces. Never store a credential in a var; use `primitive secrets`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerVarsCommands(program: Command): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ApiClient } from "../lib/api-client.js";
|
|
2
|
+
import { resolveAppId } from "../lib/config.js";
|
|
3
|
+
import { success, error, info, keyValue, formatTable, formatDate, json, } from "../lib/output.js";
|
|
4
|
+
/**
|
|
5
|
+
* `primitive vars` — non-secret per-app config scalars (issue #1364). The
|
|
6
|
+
* plaintext twin of `primitive secrets`: same key format and limits, but
|
|
7
|
+
* values are NOT secret — `list` shows them, and they appear unmasked in
|
|
8
|
+
* debug traces. Never store a credential in a var; use `primitive secrets`.
|
|
9
|
+
*/
|
|
10
|
+
export function registerVarsCommands(program) {
|
|
11
|
+
const vars = program
|
|
12
|
+
.command("vars")
|
|
13
|
+
.description("Manage non-secret app config vars (values are visible; use secrets for credentials)")
|
|
14
|
+
.addHelpText("after", `
|
|
15
|
+
Examples:
|
|
16
|
+
$ primitive vars list
|
|
17
|
+
$ primitive vars set ADMIN_GROUP_ID --value grp_01ABC --summary "Admins group id"
|
|
18
|
+
$ primitive vars set ADMIN_GROUP_ID --value grp_01NEW (updates existing)
|
|
19
|
+
$ primitive vars delete ADMIN_GROUP_ID
|
|
20
|
+
|
|
21
|
+
Vars bind into CEL rules via the declared \`vars.*\` namespace — declare them
|
|
22
|
+
with \`vars = ["ADMIN_GROUP_ID"]\` in the config's access manifest.
|
|
23
|
+
`);
|
|
24
|
+
// List vars (values shown — non-secret)
|
|
25
|
+
vars
|
|
26
|
+
.command("list")
|
|
27
|
+
.description("List all config vars for an app (values are shown)")
|
|
28
|
+
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
29
|
+
.option("--json", "Output as JSON")
|
|
30
|
+
.action(async (options) => {
|
|
31
|
+
const resolvedAppId = resolveAppId(undefined, options);
|
|
32
|
+
const client = new ApiClient();
|
|
33
|
+
try {
|
|
34
|
+
const varsList = await client.listAppConfigVars(resolvedAppId);
|
|
35
|
+
if (options.json) {
|
|
36
|
+
json(varsList);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!varsList || varsList.length === 0) {
|
|
40
|
+
info("No vars found.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(formatTable(varsList, [
|
|
44
|
+
{ header: "KEY", key: "key" },
|
|
45
|
+
{ header: "VALUE", key: "value" },
|
|
46
|
+
{ header: "SUMMARY", key: "summary" },
|
|
47
|
+
{ header: "CREATED", key: "createdAt", format: formatDate },
|
|
48
|
+
{ header: "UPDATED", key: "updatedAt", format: formatDate },
|
|
49
|
+
]));
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
error(err.message);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Set var (create or update — by-key upsert)
|
|
57
|
+
vars
|
|
58
|
+
.command("set")
|
|
59
|
+
.description("Create or update a config var")
|
|
60
|
+
.argument("<key>", "Var key (e.g., ADMIN_GROUP_ID)")
|
|
61
|
+
.option("--value <value>", "Var value (non-secret)")
|
|
62
|
+
.option("--summary <text>", "Description of the var")
|
|
63
|
+
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
64
|
+
.option("--json", "Output as JSON")
|
|
65
|
+
.action(async (key, options) => {
|
|
66
|
+
const resolvedAppId = resolveAppId(undefined, options);
|
|
67
|
+
if (!options.value) {
|
|
68
|
+
error("--value is required");
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const client = new ApiClient();
|
|
72
|
+
try {
|
|
73
|
+
const payload = { value: options.value };
|
|
74
|
+
if (options.summary !== undefined) {
|
|
75
|
+
payload.summary = options.summary;
|
|
76
|
+
}
|
|
77
|
+
const result = await client.upsertAppConfigVar(resolvedAppId, key, payload);
|
|
78
|
+
if (options.json) {
|
|
79
|
+
json(result);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
success(`Var '${key}' saved.`);
|
|
83
|
+
keyValue("Key", result?.key || key);
|
|
84
|
+
keyValue("Value", result?.value ?? options.value);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
error(err.message);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
// Delete var (key-addressed — no id lookup needed)
|
|
92
|
+
vars
|
|
93
|
+
.command("delete")
|
|
94
|
+
.description("Delete a config var")
|
|
95
|
+
.argument("<key>", "Var key (e.g., ADMIN_GROUP_ID)")
|
|
96
|
+
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
97
|
+
.action(async (key, options) => {
|
|
98
|
+
const resolvedAppId = resolveAppId(undefined, options);
|
|
99
|
+
const client = new ApiClient();
|
|
100
|
+
try {
|
|
101
|
+
await client.deleteAppConfigVar(resolvedAppId, key);
|
|
102
|
+
success(`Var '${key}' deleted.`);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
error(err.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=vars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vars.js","sourceRoot":"","sources":["../../../src/commands/vars.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, statSync } from "fs";
|
|
1
|
+
import { readFileSync, writeFileSync, statSync, readdirSync, } from "fs";
|
|
2
2
|
import { basename } from "path";
|
|
3
|
+
import * as path from "path";
|
|
3
4
|
import { parseConfigToml, stringifyConfigToml } from "../lib/config-toml.js";
|
|
4
5
|
import { lookup as mimeLookup } from "mime-types";
|
|
6
|
+
import { generateWorkflowTypes, } from "../lib/workflow-codegen/generator.js";
|
|
5
7
|
import { ApiClient } from "../lib/api-client.js";
|
|
6
8
|
import { resolveAppId } from "../lib/config.js";
|
|
9
|
+
import { resolveCodegenSourceDir } from "../lib/codegen-shared/resolveCodegenSourceDir.js";
|
|
7
10
|
import { validateWorkflowToml, formatWorkflowTomlErrors, } from "../lib/workflow-toml-validator.js";
|
|
8
11
|
import { expandWorkflow } from "../lib/workflow-fragments.js";
|
|
9
12
|
import { buildWorkflowPayloadFromToml } from "../lib/workflow-payload.js";
|
|
@@ -246,7 +249,7 @@ Examples:
|
|
|
246
249
|
workflows
|
|
247
250
|
.command("get")
|
|
248
251
|
.description("Get workflow details")
|
|
249
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
252
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
250
253
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
251
254
|
.option("--json", "Output as JSON")
|
|
252
255
|
.action(async (workflowId, options) => {
|
|
@@ -327,7 +330,7 @@ Examples:
|
|
|
327
330
|
workflows
|
|
328
331
|
.command("update")
|
|
329
332
|
.description("Update workflow metadata, or push a new body with --from-file")
|
|
330
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
333
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
331
334
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
332
335
|
.option("--name <name>", "Display name")
|
|
333
336
|
.option("--description <desc>", "Description")
|
|
@@ -506,7 +509,7 @@ Examples:
|
|
|
506
509
|
workflows
|
|
507
510
|
.command("delete")
|
|
508
511
|
.description("Delete or archive a workflow")
|
|
509
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
512
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
510
513
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
511
514
|
.option("--hard", "Permanently delete instead of archive")
|
|
512
515
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
@@ -573,7 +576,7 @@ Examples:
|
|
|
573
576
|
draft
|
|
574
577
|
.command("update")
|
|
575
578
|
.description("Update workflow draft steps (deprecated; use 'workflows configs' for staged rollouts)")
|
|
576
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
579
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
577
580
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
578
581
|
.option("--from-file <path>", "Load steps from TOML file")
|
|
579
582
|
.option("--json", "Output as JSON")
|
|
@@ -642,7 +645,7 @@ Examples:
|
|
|
642
645
|
workflows
|
|
643
646
|
.command("publish")
|
|
644
647
|
.description("Publish the current draft as a new revision (deprecated for new-model workflows; use 'workflows configs activate')")
|
|
645
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
648
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
646
649
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
647
650
|
.option("--json", "Output as JSON")
|
|
648
651
|
.action(async (workflowId, options) => {
|
|
@@ -686,7 +689,7 @@ Examples:
|
|
|
686
689
|
workflows
|
|
687
690
|
.command("preview")
|
|
688
691
|
.description("Run a preview execution of the workflow")
|
|
689
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
692
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
690
693
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
691
694
|
.option("--config <config-id>", "Use specific configuration")
|
|
692
695
|
.option("--draft", "Force preview of the draft version, even if active is newer")
|
|
@@ -841,7 +844,7 @@ Examples:
|
|
|
841
844
|
runs
|
|
842
845
|
.command("list")
|
|
843
846
|
.description("List workflow runs")
|
|
844
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
847
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
845
848
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
846
849
|
.option("--status <status>", "Filter by status: pending, running, completed, failed")
|
|
847
850
|
.option("--limit <n>", "Number of runs to show", "20")
|
|
@@ -879,7 +882,7 @@ Examples:
|
|
|
879
882
|
runs
|
|
880
883
|
.command("status")
|
|
881
884
|
.description("Get status of a workflow run")
|
|
882
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
885
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
883
886
|
.argument("<run-id>", "Run ID")
|
|
884
887
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
885
888
|
.option("--json", "Output as JSON")
|
|
@@ -928,7 +931,7 @@ Examples:
|
|
|
928
931
|
runs
|
|
929
932
|
.command("steps")
|
|
930
933
|
.description("Show step-level details for a workflow run")
|
|
931
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
934
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
932
935
|
.argument("<run-id>", "Run ID")
|
|
933
936
|
.option("--app <app-id>", "App ID")
|
|
934
937
|
.option("--json", "Output as JSON")
|
|
@@ -978,7 +981,7 @@ Examples:
|
|
|
978
981
|
runs
|
|
979
982
|
.command("step-detail")
|
|
980
983
|
.description("Show full details for a single step")
|
|
981
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
984
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
982
985
|
.argument("<run-id>", "Run ID")
|
|
983
986
|
.argument("<step-id>", "Step ID")
|
|
984
987
|
.option("--app <app-id>", "App ID")
|
|
@@ -1100,7 +1103,7 @@ Examples:
|
|
|
1100
1103
|
runs
|
|
1101
1104
|
.command("error")
|
|
1102
1105
|
.description("Show error details for a failed workflow run")
|
|
1103
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1106
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1104
1107
|
.argument("<run-id>", "Run ID")
|
|
1105
1108
|
.option("--app <app-id>", "App ID")
|
|
1106
1109
|
.option("--json", "Output as JSON")
|
|
@@ -1169,7 +1172,7 @@ Examples:
|
|
|
1169
1172
|
runs
|
|
1170
1173
|
.command("failures")
|
|
1171
1174
|
.description("List recent workflow run failures")
|
|
1172
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1175
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1173
1176
|
.option("--app <app-id>", "App ID")
|
|
1174
1177
|
.option("--limit <n>", "Number of failures to show", "10")
|
|
1175
1178
|
.option("--json", "Output as JSON")
|
|
@@ -1398,7 +1401,7 @@ Examples:
|
|
|
1398
1401
|
configs
|
|
1399
1402
|
.command("list")
|
|
1400
1403
|
.description("List configurations for a workflow")
|
|
1401
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1404
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1402
1405
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1403
1406
|
.option("--json", "Output as JSON")
|
|
1404
1407
|
.action(async (workflowId, options) => {
|
|
@@ -1438,7 +1441,7 @@ Examples:
|
|
|
1438
1441
|
configs
|
|
1439
1442
|
.command("get")
|
|
1440
1443
|
.description("Get configuration details")
|
|
1441
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1444
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1442
1445
|
.argument("<config-id>", "Configuration ID")
|
|
1443
1446
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1444
1447
|
.option("--json", "Output as JSON")
|
|
@@ -1474,7 +1477,7 @@ Examples:
|
|
|
1474
1477
|
configs
|
|
1475
1478
|
.command("create")
|
|
1476
1479
|
.description("Create a new configuration")
|
|
1477
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1480
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1478
1481
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1479
1482
|
.option("--name <name>", "Configuration name (required)")
|
|
1480
1483
|
.option("--description <desc>", "Description")
|
|
@@ -1528,7 +1531,7 @@ Examples:
|
|
|
1528
1531
|
configs
|
|
1529
1532
|
.command("update")
|
|
1530
1533
|
.description("Update a configuration")
|
|
1531
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1534
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1532
1535
|
.argument("<config-id>", "Configuration ID")
|
|
1533
1536
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1534
1537
|
.option("--name <name>", "Configuration name")
|
|
@@ -1584,7 +1587,7 @@ Examples:
|
|
|
1584
1587
|
configs
|
|
1585
1588
|
.command("activate")
|
|
1586
1589
|
.description("Set a configuration as the active (default) configuration")
|
|
1587
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1590
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1588
1591
|
.argument("<config-id>", "Configuration ID")
|
|
1589
1592
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1590
1593
|
.option("--json", "Output as JSON")
|
|
@@ -1609,7 +1612,7 @@ Examples:
|
|
|
1609
1612
|
configs
|
|
1610
1613
|
.command("duplicate")
|
|
1611
1614
|
.description("Duplicate a configuration")
|
|
1612
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1615
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1613
1616
|
.argument("<config-id>", "Configuration ID to duplicate")
|
|
1614
1617
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1615
1618
|
.option("--name <name>", "Name for the new configuration")
|
|
@@ -1637,7 +1640,7 @@ Examples:
|
|
|
1637
1640
|
configs
|
|
1638
1641
|
.command("archive")
|
|
1639
1642
|
.description("Archive a configuration")
|
|
1640
|
-
.argument("<workflow-id>", "Workflow ID")
|
|
1643
|
+
.argument("<workflow-id>", "Workflow ID or key")
|
|
1641
1644
|
.argument("<config-id>", "Configuration ID")
|
|
1642
1645
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1643
1646
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
@@ -2456,6 +2459,109 @@ Examples:
|
|
|
2456
2459
|
process.exit(1);
|
|
2457
2460
|
}
|
|
2458
2461
|
});
|
|
2462
|
+
// ============================================
|
|
2463
|
+
// Codegen command (issue #1442)
|
|
2464
|
+
// ============================================
|
|
2465
|
+
workflows
|
|
2466
|
+
.command("codegen")
|
|
2467
|
+
.description("Generate typed TypeScript signatures from the local workflows/*.toml schemas. Emits one <key>.generated.ts per workflow (<Key>Input/<Key>Output types + a <key>(client) typed invoker factory returning { runSync?, start }).")
|
|
2468
|
+
.argument("[workflow-key]", "Generate for a single workflow (defaults to every workflows/*.toml found)")
|
|
2469
|
+
.option("--app <app-id>", "App ID")
|
|
2470
|
+
.option("--sync-dir <path>", "Override path to the sync directory (defaults to ./.primitive/sync/<env>/<appId>/)")
|
|
2471
|
+
.option("-o, --output <dir>", "Output directory for the <key>.generated.ts files (defaults to <sync-dir>/workflows/generated/)")
|
|
2472
|
+
.option("--check", "Exit non-zero if generated output is out of date (CI guard); does not write.")
|
|
2473
|
+
.option("--json", "Output the result summary as JSON")
|
|
2474
|
+
.action(async (workflowKey, options) => {
|
|
2475
|
+
try {
|
|
2476
|
+
// 1. Resolve the single source workflows/ directory via the shared
|
|
2477
|
+
// active-environment resolver (issue #1510). Honors --sync-dir /
|
|
2478
|
+
// --app overrides, resolves the active env
|
|
2479
|
+
// (--env → PRIMITIVE_ENV → defaultEnvironment → single-env), and
|
|
2480
|
+
// preserves the legacy per-app scan fallback in bare-dir mode.
|
|
2481
|
+
const workflowsSourceDir = resolveCodegenSourceDir({
|
|
2482
|
+
subdir: "workflows",
|
|
2483
|
+
options: { app: options.app, syncDir: options.syncDir },
|
|
2484
|
+
});
|
|
2485
|
+
// 2. Collect the source .toml files (one per workflow), filtered to a
|
|
2486
|
+
// single workflow when an argument is given. Match on the file stem;
|
|
2487
|
+
// the generator resolves the real key from `[workflow].key`.
|
|
2488
|
+
const inputs = [];
|
|
2489
|
+
for (const fileName of readdirSync(workflowsSourceDir)) {
|
|
2490
|
+
if (!fileName.endsWith(".toml"))
|
|
2491
|
+
continue;
|
|
2492
|
+
const stem = fileName.slice(0, -".toml".length);
|
|
2493
|
+
if (workflowKey && stem !== workflowKey)
|
|
2494
|
+
continue;
|
|
2495
|
+
const tomlPath = path.join(workflowsSourceDir, fileName);
|
|
2496
|
+
inputs.push({
|
|
2497
|
+
fileStem: stem,
|
|
2498
|
+
tomlPath,
|
|
2499
|
+
tomlContent: readFileSync(tomlPath, "utf-8"),
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
if (inputs.length === 0) {
|
|
2503
|
+
error(workflowKey
|
|
2504
|
+
? `No workflows/${workflowKey}.toml found under .primitive/sync/.`
|
|
2505
|
+
: "No workflows/*.toml files found to generate from.");
|
|
2506
|
+
process.exit(1);
|
|
2507
|
+
}
|
|
2508
|
+
// 3. Resolve the output directory. Default: a `generated/` subdir of
|
|
2509
|
+
// the first source dir (keeps generated output beside the schema).
|
|
2510
|
+
const outputDir = options.output
|
|
2511
|
+
? path.resolve(options.output)
|
|
2512
|
+
: path.join(path.dirname(inputs[0].tomlPath), "generated");
|
|
2513
|
+
// 4. Run codegen (or --check).
|
|
2514
|
+
const codegenResult = await generateWorkflowTypes({
|
|
2515
|
+
inputs,
|
|
2516
|
+
outputDir,
|
|
2517
|
+
check: !!options.check,
|
|
2518
|
+
singleWorkflow: !!workflowKey,
|
|
2519
|
+
});
|
|
2520
|
+
if (options.check) {
|
|
2521
|
+
if (codegenResult.mismatches.length > 0) {
|
|
2522
|
+
if (options.json) {
|
|
2523
|
+
json({ ok: false, mismatches: codegenResult.mismatches });
|
|
2524
|
+
}
|
|
2525
|
+
else {
|
|
2526
|
+
error(`Check failed: ${codegenResult.mismatches.length} file(s) out of date.`);
|
|
2527
|
+
for (const m of codegenResult.mismatches) {
|
|
2528
|
+
error(` ${m.reason}: ${path.relative(process.cwd(), m.filePath)}`);
|
|
2529
|
+
}
|
|
2530
|
+
info("Run `primitive workflows codegen` to regenerate.");
|
|
2531
|
+
}
|
|
2532
|
+
process.exit(1);
|
|
2533
|
+
}
|
|
2534
|
+
if (options.json) {
|
|
2535
|
+
json({ ok: true, checked: codegenResult.writtenFiles.length });
|
|
2536
|
+
}
|
|
2537
|
+
else {
|
|
2538
|
+
success(`Check passed: ${codegenResult.writtenFiles.length} file(s) up to date.`);
|
|
2539
|
+
}
|
|
2540
|
+
return;
|
|
2541
|
+
}
|
|
2542
|
+
if (options.json) {
|
|
2543
|
+
json({
|
|
2544
|
+
written: codegenResult.writtenFiles,
|
|
2545
|
+
deleted: codegenResult.deletedFiles,
|
|
2546
|
+
});
|
|
2547
|
+
return;
|
|
2548
|
+
}
|
|
2549
|
+
success(`Generated ${codegenResult.writtenFiles.length} file(s)` +
|
|
2550
|
+
(codegenResult.deletedFiles.length > 0
|
|
2551
|
+
? `, deleted ${codegenResult.deletedFiles.length} stale file(s).`
|
|
2552
|
+
: "."));
|
|
2553
|
+
for (const f of codegenResult.writtenFiles) {
|
|
2554
|
+
keyValue(" wrote", path.relative(process.cwd(), f));
|
|
2555
|
+
}
|
|
2556
|
+
for (const f of codegenResult.deletedFiles) {
|
|
2557
|
+
keyValue(" deleted", path.relative(process.cwd(), f));
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
catch (err) {
|
|
2561
|
+
error(err.message);
|
|
2562
|
+
process.exit(1);
|
|
2563
|
+
}
|
|
2564
|
+
});
|
|
2459
2565
|
}
|
|
2460
2566
|
function formatFileSize(bytes) {
|
|
2461
2567
|
if (bytes < 1024)
|