primitive-admin 1.1.0-alpha.75 → 1.1.0-alpha.76
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 +98 -10
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/functions.js +53 -18
- package/dist/src/commands/functions.js.map +1 -1
- package/dist/src/commands/prompts.js +54 -39
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/sync.d.ts +39 -0
- package/dist/src/commands/sync.js +163 -90
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/workflows.js +61 -30
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +16 -1
- package/dist/src/lib/api-client.js +16 -3
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/block-selector.d.ts +58 -0
- package/dist/src/lib/block-selector.js +92 -0
- package/dist/src/lib/block-selector.js.map +1 -0
- package/dist/src/lib/config-object-descriptor.js +1 -3
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/function-collect.d.ts +29 -7
- package/dist/src/lib/function-collect.js +135 -11
- package/dist/src/lib/function-collect.js.map +1 -1
- package/dist/src/lib/function-grants-preflight.d.ts +34 -88
- package/dist/src/lib/function-grants-preflight.js +32 -145
- package/dist/src/lib/function-grants-preflight.js.map +1 -1
- package/dist/src/lib/function-sync.d.ts +3 -14
- package/dist/src/lib/function-sync.js +10 -49
- package/dist/src/lib/function-sync.js.map +1 -1
- package/dist/src/lib/function-triggers.d.ts +6 -0
- package/dist/src/lib/function-triggers.js +63 -4
- package/dist/src/lib/function-triggers.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.d.ts +188 -236
- package/dist/src/lib/generated-config-surfaces.js +355 -453
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/toml-database-config.js +19 -2
- package/dist/src/lib/toml-database-config.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { generateWorkflowTypes, } from "../lib/workflow-codegen/generator.js";
|
|
|
6
6
|
import { generateWorkflowSwiftTypes } from "../lib/swift-codegen/generator.js";
|
|
7
7
|
import { ApiClient } from "../lib/api-client.js";
|
|
8
8
|
import { resolveAppId } from "../lib/config.js";
|
|
9
|
+
import { resolveWorkflowSelector } from "../lib/block-selector.js";
|
|
9
10
|
import { formatAccessRuleForDisplay } from "../lib/access-rule-display.js";
|
|
10
11
|
import { resolveCodegenSourceDir } from "../lib/codegen-shared/resolveCodegenSourceDir.js";
|
|
11
12
|
import { resolveSyncDirOverride } from "../lib/sync-dir-selector.js";
|
|
@@ -254,6 +255,17 @@ export function formatConfigSlotLabel(slot, configName, configId, prefixLength =
|
|
|
254
255
|
}
|
|
255
256
|
return slot;
|
|
256
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Resolve a workflow reference — its server id, or the author-chosen key its
|
|
260
|
+
* TOML file is named for — for the `tests` verbs (#3249).
|
|
261
|
+
*
|
|
262
|
+
* The key is what an operator has: `workflows/<key>.toml` is the object and
|
|
263
|
+
* `workflows/<key>.tests/` its cases. The resolution lives in
|
|
264
|
+
* `block-selector.ts`, shared with `prompts`.
|
|
265
|
+
*/
|
|
266
|
+
async function resolveWorkflowId(client, appId, ref) {
|
|
267
|
+
return (await resolveWorkflowSelector(client, appId, ref)).blockId;
|
|
268
|
+
}
|
|
257
269
|
export function registerWorkflowsCommands(program) {
|
|
258
270
|
const workflows = program
|
|
259
271
|
.command("workflows")
|
|
@@ -1810,22 +1822,30 @@ Test cases are authored in TOML at workflows/<key>.tests/<name>.toml and applied
|
|
|
1810
1822
|
with \`primitive config push\` (issue #2769); \`config fields workflow\` lists the
|
|
1811
1823
|
fields. Deleting a case is removing its file and running \`config push --prune\`.
|
|
1812
1824
|
|
|
1825
|
+
Every verb here takes the workflow's KEY or its ID (#3249). An identifier
|
|
1826
|
+
that names no workflow in the app fails; "No test cases found." only ever
|
|
1827
|
+
means the workflow exists and has no cases.
|
|
1828
|
+
|
|
1813
1829
|
Examples:
|
|
1814
|
-
$ primitive workflows tests list <workflow
|
|
1815
|
-
$ primitive workflows tests run <workflow
|
|
1816
|
-
$ primitive workflows tests run-all <workflow
|
|
1817
|
-
$ primitive workflows tests run-all <workflow
|
|
1830
|
+
$ primitive workflows tests list <workflow>
|
|
1831
|
+
$ primitive workflows tests run <workflow> <test-case-id>
|
|
1832
|
+
$ primitive workflows tests run-all <workflow>
|
|
1833
|
+
$ primitive workflows tests run-all <workflow> --test-cases 01ABC,01DEF,01GHI
|
|
1818
1834
|
`);
|
|
1819
1835
|
tests
|
|
1820
1836
|
.command("list")
|
|
1821
1837
|
.description("List test cases for a workflow")
|
|
1822
|
-
.argument("<workflow
|
|
1838
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
1823
1839
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1824
1840
|
.option("--json", "Output as JSON")
|
|
1825
|
-
.action(async (
|
|
1841
|
+
.action(async (workflow, options) => {
|
|
1826
1842
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
1827
1843
|
const client = new ApiClient();
|
|
1828
1844
|
try {
|
|
1845
|
+
// #3249 — resolve BEFORE listing: the test-case endpoint answers an
|
|
1846
|
+
// unknown block with an empty page, so an unresolved identifier would
|
|
1847
|
+
// print "No test cases found." and exit 0.
|
|
1848
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
1829
1849
|
const { items } = await client.listTestCases(resolvedAppId, "workflow", workflowId);
|
|
1830
1850
|
if (options.json) {
|
|
1831
1851
|
json(items);
|
|
@@ -1850,14 +1870,15 @@ Examples:
|
|
|
1850
1870
|
tests
|
|
1851
1871
|
.command("get")
|
|
1852
1872
|
.description("Get test case details")
|
|
1853
|
-
.argument("<workflow
|
|
1873
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
1854
1874
|
.argument("<test-case-id>", "Test Case ID")
|
|
1855
1875
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1856
1876
|
.option("--json", "Output as JSON")
|
|
1857
|
-
.action(async (
|
|
1877
|
+
.action(async (workflow, testCaseId, options) => {
|
|
1858
1878
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
1859
1879
|
const client = new ApiClient();
|
|
1860
1880
|
try {
|
|
1881
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
1861
1882
|
const result = await client.getTestCase(resolvedAppId, "workflow", workflowId, testCaseId);
|
|
1862
1883
|
if (options.json) {
|
|
1863
1884
|
json(result);
|
|
@@ -1917,14 +1938,15 @@ Examples:
|
|
|
1917
1938
|
tests
|
|
1918
1939
|
.command("run")
|
|
1919
1940
|
.description("Run a single test case")
|
|
1920
|
-
.argument("<workflow
|
|
1941
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
1921
1942
|
.argument("<test-case-id>", "Test Case ID")
|
|
1922
1943
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1923
1944
|
.option("--json", "Output as JSON")
|
|
1924
|
-
.action(async (
|
|
1945
|
+
.action(async (workflow, testCaseId, options) => {
|
|
1925
1946
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
1926
1947
|
const client = new ApiClient();
|
|
1927
1948
|
try {
|
|
1949
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
1928
1950
|
// Get test case to retrieve its variables
|
|
1929
1951
|
const testCase = await client.getTestCase(resolvedAppId, "workflow", workflowId, testCaseId);
|
|
1930
1952
|
// #3158 — the case's stored input IS the run's input, and the server
|
|
@@ -1983,14 +2005,17 @@ Examples:
|
|
|
1983
2005
|
tests
|
|
1984
2006
|
.command("run-all")
|
|
1985
2007
|
.description("Run all test cases for a workflow, or a specific subset")
|
|
1986
|
-
.argument("<workflow
|
|
2008
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
1987
2009
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
1988
2010
|
.option("--test-cases <ids>", "Comma-separated list of test case IDs to run (runs only these)")
|
|
1989
2011
|
.option("--json", "Output as JSON")
|
|
1990
|
-
.action(async (
|
|
2012
|
+
.action(async (workflow, options) => {
|
|
1991
2013
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
1992
2014
|
const client = new ApiClient();
|
|
1993
2015
|
try {
|
|
2016
|
+
// #3249 — resolve first, so `Total Tests: 0` can only ever mean the
|
|
2017
|
+
// workflow exists and has no cases, never that the identifier was wrong.
|
|
2018
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
1994
2019
|
// Parse test case IDs if provided
|
|
1995
2020
|
let testCaseIds;
|
|
1996
2021
|
if (options.testCases) {
|
|
@@ -2047,15 +2072,16 @@ Examples:
|
|
|
2047
2072
|
tests
|
|
2048
2073
|
.command("runs")
|
|
2049
2074
|
.description("List recent test runs for a workflow")
|
|
2050
|
-
.argument("<workflow
|
|
2075
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2051
2076
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2052
2077
|
.option("--limit <n>", "Maximum number of runs to show", "20")
|
|
2053
2078
|
.option("--group <group>", "Filter by comparison group")
|
|
2054
2079
|
.option("--json", "Output as JSON")
|
|
2055
|
-
.action(async (
|
|
2080
|
+
.action(async (workflow, options) => {
|
|
2056
2081
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2057
2082
|
const client = new ApiClient();
|
|
2058
2083
|
try {
|
|
2084
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2059
2085
|
const { items } = await client.listTestRuns(resolvedAppId, "workflow", workflowId, {
|
|
2060
2086
|
limit: parseInt(options.limit),
|
|
2061
2087
|
comparisonGroup: options.group,
|
|
@@ -2097,23 +2123,24 @@ Examples:
|
|
|
2097
2123
|
.description("Run tests in parallel using workflow-based execution")
|
|
2098
2124
|
.addHelpText("after", `
|
|
2099
2125
|
Examples:
|
|
2100
|
-
$ primitive workflows tests batch start <workflow
|
|
2101
|
-
$ primitive workflows tests batch start <workflow
|
|
2102
|
-
$ primitive workflows tests batch status <workflow
|
|
2103
|
-
$ primitive workflows tests batch cancel <workflow
|
|
2126
|
+
$ primitive workflows tests batch start <workflow>
|
|
2127
|
+
$ primitive workflows tests batch start <workflow> --test-cases 01ABC,01DEF
|
|
2128
|
+
$ primitive workflows tests batch status <workflow> <batch-id>
|
|
2129
|
+
$ primitive workflows tests batch cancel <workflow> <batch-id>
|
|
2104
2130
|
`);
|
|
2105
2131
|
// Start batch tests
|
|
2106
2132
|
batch
|
|
2107
2133
|
.command("start")
|
|
2108
2134
|
.description("Start parallel batch test execution")
|
|
2109
|
-
.argument("<workflow
|
|
2135
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2110
2136
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2111
2137
|
.option("--test-cases <ids>", "Comma-separated list of test case IDs to run")
|
|
2112
2138
|
.option("--json", "Output as JSON")
|
|
2113
|
-
.action(async (
|
|
2139
|
+
.action(async (workflow, options) => {
|
|
2114
2140
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2115
2141
|
const client = new ApiClient();
|
|
2116
2142
|
try {
|
|
2143
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2117
2144
|
let testCaseIds;
|
|
2118
2145
|
if (options.testCases) {
|
|
2119
2146
|
testCaseIds = options.testCases.split(",").map((id) => id.trim()).filter(Boolean);
|
|
@@ -2149,15 +2176,16 @@ Examples:
|
|
|
2149
2176
|
batch
|
|
2150
2177
|
.command("status")
|
|
2151
2178
|
.description("Get status of a batch test execution")
|
|
2152
|
-
.argument("<workflow
|
|
2179
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2153
2180
|
.argument("<batch-id>", "Batch ID")
|
|
2154
2181
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2155
2182
|
.option("--wait", "Wait for completion (polls every 2 seconds)")
|
|
2156
2183
|
.option("--json", "Output as JSON")
|
|
2157
|
-
.action(async (
|
|
2184
|
+
.action(async (workflow, batchId, options) => {
|
|
2158
2185
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2159
2186
|
const client = new ApiClient();
|
|
2160
2187
|
try {
|
|
2188
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2161
2189
|
const fetchStatus = async () => {
|
|
2162
2190
|
return client.getBatchTestStatus(resolvedAppId, "workflow", workflowId, batchId);
|
|
2163
2191
|
};
|
|
@@ -2214,12 +2242,12 @@ Examples:
|
|
|
2214
2242
|
batch
|
|
2215
2243
|
.command("cancel")
|
|
2216
2244
|
.description("Cancel a running batch test execution")
|
|
2217
|
-
.argument("<workflow
|
|
2245
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2218
2246
|
.argument("<batch-id>", "Batch ID")
|
|
2219
2247
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2220
2248
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
2221
2249
|
.option("--json", "Output as JSON")
|
|
2222
|
-
.action(async (
|
|
2250
|
+
.action(async (workflow, batchId, options) => {
|
|
2223
2251
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2224
2252
|
if (!options.yes) {
|
|
2225
2253
|
let confirm;
|
|
@@ -2237,6 +2265,7 @@ Examples:
|
|
|
2237
2265
|
}
|
|
2238
2266
|
const client = new ApiClient();
|
|
2239
2267
|
try {
|
|
2268
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2240
2269
|
// First get current status to get instance IDs
|
|
2241
2270
|
const status = await client.getBatchTestStatus(resolvedAppId, "workflow", workflowId, batchId);
|
|
2242
2271
|
// Get instance IDs that are still running
|
|
@@ -2276,21 +2305,22 @@ with \`primitive config push\` (#2769); removing one and running
|
|
|
2276
2305
|
\`config push --prune\` deletes it server-side. These verbs read server state.
|
|
2277
2306
|
|
|
2278
2307
|
Examples:
|
|
2279
|
-
$ primitive workflows tests attachments list <workflow
|
|
2280
|
-
$ primitive workflows tests attachments download <workflow
|
|
2308
|
+
$ primitive workflows tests attachments list <workflow> <test-case-id>
|
|
2309
|
+
$ primitive workflows tests attachments download <workflow> <test-case-id> document.pdf
|
|
2281
2310
|
`);
|
|
2282
2311
|
// List attachments
|
|
2283
2312
|
attachments
|
|
2284
2313
|
.command("list")
|
|
2285
2314
|
.description("List attachments for a test case")
|
|
2286
|
-
.argument("<workflow
|
|
2315
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2287
2316
|
.argument("<test-case-id>", "Test Case ID")
|
|
2288
2317
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2289
2318
|
.option("--json", "Output as JSON")
|
|
2290
|
-
.action(async (
|
|
2319
|
+
.action(async (workflow, testCaseId, options) => {
|
|
2291
2320
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2292
2321
|
const client = new ApiClient();
|
|
2293
2322
|
try {
|
|
2323
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2294
2324
|
const result = await client.listTestCaseAttachments(resolvedAppId, "workflow", workflowId, testCaseId);
|
|
2295
2325
|
if (options.json) {
|
|
2296
2326
|
json(result.attachments);
|
|
@@ -2319,15 +2349,16 @@ Examples:
|
|
|
2319
2349
|
attachments
|
|
2320
2350
|
.command("download")
|
|
2321
2351
|
.description("Download a file attachment from a test case")
|
|
2322
|
-
.argument("<workflow
|
|
2352
|
+
.argument("<workflow>", "Workflow key or ID")
|
|
2323
2353
|
.argument("<test-case-id>", "Test Case ID")
|
|
2324
2354
|
.argument("<filename>", "Name of the file to download")
|
|
2325
2355
|
.argument("[output-path]", "Output path (defaults to current directory)")
|
|
2326
2356
|
.option("--app <app-id>", "App ID (uses current app if not specified)")
|
|
2327
|
-
.action(async (
|
|
2357
|
+
.action(async (workflow, testCaseId, filename, outputPath, options) => {
|
|
2328
2358
|
const resolvedAppId = resolveAppId(undefined, options);
|
|
2329
2359
|
const client = new ApiClient();
|
|
2330
2360
|
try {
|
|
2361
|
+
const workflowId = await resolveWorkflowId(client, resolvedAppId, workflow);
|
|
2331
2362
|
const result = await client.downloadTestCaseAttachment(resolvedAppId, "workflow", workflowId, testCaseId, filename);
|
|
2332
2363
|
const finalPath = outputPath || filename;
|
|
2333
2364
|
writeFileSync(finalPath, result.data);
|