@withandeo/cli 0.10.0 → 0.12.0
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/README.md +24 -2
- package/dist/api.d.ts +13 -7
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +24 -6
- package/dist/api.js.map +1 -1
- package/dist/artifact-limits.d.ts +8 -0
- package/dist/artifact-limits.d.ts.map +1 -0
- package/dist/artifact-limits.js +10 -0
- package/dist/artifact-limits.js.map +1 -0
- package/dist/artifact.d.ts.map +1 -1
- package/dist/artifact.js +28 -11
- package/dist/artifact.js.map +1 -1
- package/dist/contracts.d.ts +33 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/errors.d.ts +3 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -3
- package/dist/errors.js.map +1 -1
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +16 -1
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +170 -23
- package/dist/main.js.map +1 -1
- package/dist/workflow-config.d.ts +9 -0
- package/dist/workflow-config.d.ts.map +1 -0
- package/dist/workflow-config.js +76 -0
- package/dist/workflow-config.js.map +1 -0
- package/dist/workflow-contract.d.ts +34 -0
- package/dist/workflow-contract.d.ts.map +1 -0
- package/dist/workflow-contract.js +96 -0
- package/dist/workflow-contract.js.map +1 -0
- package/dist/workflow-coordinator.d.ts +4 -0
- package/dist/workflow-coordinator.d.ts.map +1 -0
- package/dist/workflow-coordinator.js +49 -0
- package/dist/workflow-coordinator.js.map +1 -0
- package/dist/workflow-dev-host.d.ts +2 -0
- package/dist/workflow-dev-host.d.ts.map +1 -0
- package/dist/workflow-dev-host.js +34 -0
- package/dist/workflow-dev-host.js.map +1 -0
- package/dist/workflow-dev.d.ts +5 -0
- package/dist/workflow-dev.d.ts.map +1 -0
- package/dist/workflow-dev.js +112 -0
- package/dist/workflow-dev.js.map +1 -0
- package/dist/workflow-package.d.ts +5 -0
- package/dist/workflow-package.d.ts.map +1 -0
- package/dist/workflow-package.js +116 -0
- package/dist/workflow-package.js.map +1 -0
- package/package.json +8 -1
- package/skill/tender-accounts/SKILL.md +14 -1
- package/templates/shopify-customer-account/apps/gateway/README.md +2 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const MAX_APP_WORKFLOWS = 8;
|
|
2
|
+
export declare const MAX_COORDINATOR_BYTES: number;
|
|
3
|
+
export declare const MAX_COORDINATOR_SOURCE_MAP_BYTES: number;
|
|
4
|
+
export interface AppWorkflowDeclaration {
|
|
5
|
+
name: string;
|
|
6
|
+
binding: string;
|
|
7
|
+
class_name: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkflowFile {
|
|
10
|
+
path: "workflow.mjs" | "workflow.mjs.map";
|
|
11
|
+
sha256: string;
|
|
12
|
+
bytes: number;
|
|
13
|
+
}
|
|
14
|
+
export interface AppWorkflowArtifact {
|
|
15
|
+
schema: "andeo.app-workflows/v1";
|
|
16
|
+
declarations: AppWorkflowDeclaration[];
|
|
17
|
+
module: WorkflowFile & {
|
|
18
|
+
path: "workflow.mjs";
|
|
19
|
+
contentType: "application/javascript+module";
|
|
20
|
+
};
|
|
21
|
+
sourceMap?: WorkflowFile & {
|
|
22
|
+
path: "workflow.mjs.map";
|
|
23
|
+
};
|
|
24
|
+
compatibilityDate: string;
|
|
25
|
+
compatibilityFlags: ["nodejs_compat"];
|
|
26
|
+
vars: Record<string, string>;
|
|
27
|
+
services: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function workflowRecord(value: unknown): value is Record<string, unknown>;
|
|
30
|
+
export declare function workflowBindingName(value: unknown): value is string;
|
|
31
|
+
export declare function parseWorkflowDeclarations(value: unknown): AppWorkflowDeclaration[];
|
|
32
|
+
export declare function parseWorkflowArtifact(value: unknown): AppWorkflowArtifact | undefined;
|
|
33
|
+
export declare function workflowFiles(value: AppWorkflowArtifact | undefined): WorkflowFile[];
|
|
34
|
+
//# sourceMappingURL=workflow-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-contract.d.ts","sourceRoot":"","sources":["../src/workflow-contract.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,qBAAqB,QAAmB,CAAC;AACtD,eAAO,MAAM,gCAAgC,QAAmB,CAAC;AACjE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,GAAG,kBAAkB,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,wBAAwB,CAAC;IACjC,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC,MAAM,EAAE,YAAY,GAAG;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,WAAW,EAAE,+BAA+B,CAAA;KAAE,CAAC;IAC9F,SAAS,CAAC,EAAE,YAAY,GAAG;QAAE,IAAI,EAAE,kBAAkB,CAAA;KAAE,CAAC;IACxD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAGnE;AACD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,EAAE,CAgBlF;AACD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,SAAS,CAoCrF;AAOD,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,GAAG,YAAY,EAAE,CAEpF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Portable contract: imported by both the CLI and the trusted platform.
|
|
2
|
+
// App-defined workflows are not registered native resource bindings.
|
|
3
|
+
export const MAX_APP_WORKFLOWS = 8;
|
|
4
|
+
export const MAX_COORDINATOR_BYTES = 10 * 1024 * 1024;
|
|
5
|
+
export const MAX_COORDINATOR_SOURCE_MAP_BYTES = 10 * 1024 * 1024;
|
|
6
|
+
export function workflowRecord(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function fail(message) { throw new Error("app_workflow_invalid: " + message); }
|
|
10
|
+
export function workflowBindingName(value) {
|
|
11
|
+
return typeof value === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(value)
|
|
12
|
+
&& !value.startsWith("TENDER_") && !value.startsWith("ANDEO_") && value !== "ASSETS";
|
|
13
|
+
}
|
|
14
|
+
export function parseWorkflowDeclarations(value) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return [];
|
|
17
|
+
if (!Array.isArray(value) || value.length > MAX_APP_WORKFLOWS)
|
|
18
|
+
fail("expected at most eight workflows");
|
|
19
|
+
const names = new Set(), bindings = new Set();
|
|
20
|
+
return value.map((item) => {
|
|
21
|
+
if (!workflowRecord(item) || Object.keys(item).some(key => !["name", "binding", "class_name"].includes(key))) {
|
|
22
|
+
fail("only same-app name, binding and class_name are supported; script_name is not supported");
|
|
23
|
+
}
|
|
24
|
+
if (typeof item.name !== "string" || !/^[a-z][a-z0-9-]{0,63}$/.test(item.name))
|
|
25
|
+
fail("invalid logical name");
|
|
26
|
+
if (!workflowBindingName(item.binding))
|
|
27
|
+
fail("invalid or reserved binding");
|
|
28
|
+
if (typeof item.class_name !== "string" || !/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/.test(item.class_name)
|
|
29
|
+
|| ["default", "AndeoCoordinator"].includes(item.class_name))
|
|
30
|
+
fail("invalid named workflow export");
|
|
31
|
+
if (names.has(item.name) || bindings.has(item.binding))
|
|
32
|
+
fail("duplicate workflow name or binding");
|
|
33
|
+
names.add(item.name);
|
|
34
|
+
bindings.add(item.binding);
|
|
35
|
+
return { name: item.name, binding: item.binding, class_name: item.class_name };
|
|
36
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
37
|
+
}
|
|
38
|
+
export function parseWorkflowArtifact(value) {
|
|
39
|
+
if (value === undefined)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (!workflowRecord(value) || value.schema !== "andeo.app-workflows/v1"
|
|
42
|
+
|| Object.keys(value).some(key => !["schema", "declarations", "module", "sourceMap",
|
|
43
|
+
"compatibilityDate", "compatibilityFlags", "vars", "services"].includes(key)))
|
|
44
|
+
fail("invalid artifact shape");
|
|
45
|
+
const declarations = parseWorkflowDeclarations(value.declarations);
|
|
46
|
+
if (!declarations.length)
|
|
47
|
+
fail("empty coordinator artifact");
|
|
48
|
+
if (typeof value.compatibilityDate !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value.compatibilityDate)
|
|
49
|
+
|| !Number.isFinite(Date.parse(value.compatibilityDate))
|
|
50
|
+
|| new Date(value.compatibilityDate).toISOString().slice(0, 10) !== value.compatibilityDate)
|
|
51
|
+
fail("invalid compatibility date");
|
|
52
|
+
if (!Array.isArray(value.compatibilityFlags) || value.compatibilityFlags.length !== 1
|
|
53
|
+
|| value.compatibilityFlags[0] !== "nodejs_compat")
|
|
54
|
+
fail("only nodejs_compat is supported");
|
|
55
|
+
if (!workflowRecord(value.vars) || Object.keys(value.vars).length > 64)
|
|
56
|
+
fail("invalid public vars");
|
|
57
|
+
const vars = {};
|
|
58
|
+
let total = 0;
|
|
59
|
+
for (const [key, item] of Object.entries(value.vars).sort(([a], [b]) => a.localeCompare(b))) {
|
|
60
|
+
if (!workflowBindingName(key) || typeof item !== "string")
|
|
61
|
+
fail("vars must be named non-secret strings");
|
|
62
|
+
const bytes = new TextEncoder().encode(item).byteLength;
|
|
63
|
+
total += bytes;
|
|
64
|
+
if (bytes > 4096 || total > 65536)
|
|
65
|
+
fail("vars exceed byte limit");
|
|
66
|
+
vars[key] = item;
|
|
67
|
+
}
|
|
68
|
+
if (!Array.isArray(value.services) || value.services.length > 32
|
|
69
|
+
|| value.services.some(name => !workflowBindingName(name))
|
|
70
|
+
|| new Set(value.services).size !== value.services.length)
|
|
71
|
+
fail("invalid service capabilities");
|
|
72
|
+
const services = [...value.services];
|
|
73
|
+
if (services.some(name => name in vars || declarations.some(d => d.binding === name))
|
|
74
|
+
|| declarations.some(d => d.binding in vars))
|
|
75
|
+
fail("binding collision");
|
|
76
|
+
const module = workflowFile(value.module, "workflow.mjs", MAX_COORDINATOR_BYTES);
|
|
77
|
+
if (!workflowRecord(value.module) || value.module.contentType !== "application/javascript+module")
|
|
78
|
+
fail("invalid module type");
|
|
79
|
+
const sourceMap = value.sourceMap === undefined ? undefined
|
|
80
|
+
: workflowFile(value.sourceMap, "workflow.mjs.map", MAX_COORDINATOR_SOURCE_MAP_BYTES);
|
|
81
|
+
return { schema: "andeo.app-workflows/v1", declarations,
|
|
82
|
+
module: { ...module, contentType: "application/javascript+module" },
|
|
83
|
+
...(sourceMap ? { sourceMap } : {}), compatibilityDate: value.compatibilityDate,
|
|
84
|
+
compatibilityFlags: ["nodejs_compat"], vars, services: services.sort() };
|
|
85
|
+
}
|
|
86
|
+
function workflowFile(value, path, max) {
|
|
87
|
+
if (!workflowRecord(value) || value.path !== path || typeof value.sha256 !== "string"
|
|
88
|
+
|| !/^[a-f0-9]{64}$/.test(value.sha256) || typeof value.bytes !== "number"
|
|
89
|
+
|| !Number.isSafeInteger(value.bytes) || value.bytes < 1 || value.bytes > max)
|
|
90
|
+
fail("invalid private " + path);
|
|
91
|
+
return { path, sha256: value.sha256, bytes: value.bytes };
|
|
92
|
+
}
|
|
93
|
+
export function workflowFiles(value) {
|
|
94
|
+
return value ? [value.module, ...(value.sourceMap ? [value.sourceMap] : [])] : [];
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=workflow-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-contract.js","sourceRoot":"","sources":["../src/workflow-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Trusted wrapper in the Dynamic Worker. Run capabilities are arguments, not
|
|
2
|
+
* cached Loader env; every invocation gets its own async context. */
|
|
3
|
+
export declare function renderWorkflowCoordinator(className: string, services: string[]): string;
|
|
4
|
+
//# sourceMappingURL=workflow-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-coordinator.d.ts","sourceRoot":"","sources":["../src/workflow-coordinator.ts"],"names":[],"mappings":"AAAA;qEACqE;AACrE,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CA6CvF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Trusted wrapper in the Dynamic Worker. Run capabilities are arguments, not
|
|
2
|
+
* cached Loader env; every invocation gets its own async context. */
|
|
3
|
+
export function renderWorkflowCoordinator(className, services) {
|
|
4
|
+
return `import { WorkerEntrypoint } from "cloudflare:workers";
|
|
5
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
|
+
import { ${className} as MerchantWorkflow } from "./workflow.mjs";
|
|
7
|
+
export class AndeoCoordinator extends WorkerEntrypoint {
|
|
8
|
+
async run(event, step, runtime) {
|
|
9
|
+
const context = new AsyncLocalStorage();
|
|
10
|
+
const wrappedStep = {
|
|
11
|
+
do(name, options, callback, extra) {
|
|
12
|
+
if (typeof options === "function") { extra = callback; callback = options; options = undefined; }
|
|
13
|
+
if (extra !== undefined || (options && Object.values(options).some(v => typeof v === "function"))
|
|
14
|
+
|| (options?.retries && typeof options.retries.delay === "function")) throw new Error("app_workflow_step_options_unsupported");
|
|
15
|
+
const execute = async nativeContext => context.run({ native: nativeContext, call: 0 }, async () => {
|
|
16
|
+
await runtime.observeStep?.(nativeContext, "started").catch(() => undefined);
|
|
17
|
+
try {
|
|
18
|
+
const result = await callback(nativeContext);
|
|
19
|
+
await runtime.observeStep?.(nativeContext, "completed").catch(() => undefined);
|
|
20
|
+
return result;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
await runtime.observeStep?.(nativeContext, "errored").catch(() => undefined);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return options === undefined ? step.do(name, execute) : step.do(name, options, execute);
|
|
27
|
+
},
|
|
28
|
+
sleep: (...args) => step.sleep(...args),
|
|
29
|
+
sleepUntil: (...args) => step.sleepUntil(...args),
|
|
30
|
+
waitForEvent: (...args) => step.waitForEvent(...args),
|
|
31
|
+
};
|
|
32
|
+
const scopedEnv = { ...this.env };
|
|
33
|
+
for (const name of ${JSON.stringify(services)}) scopedEnv[name] = {
|
|
34
|
+
fetch(input, init) {
|
|
35
|
+
const current = context.getStore();
|
|
36
|
+
if (!current?.native?.step || !Number.isSafeInteger(current.native.attempt)) throw new Error("app_workflow_step_context_required");
|
|
37
|
+
return runtime.invoke(name, new Request(input, init), {
|
|
38
|
+
name: current.native.step.name, count: current.native.step.count,
|
|
39
|
+
attempt: current.native.attempt, call: ++current.call,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
const workflow = new MerchantWorkflow(this.ctx, scopedEnv);
|
|
44
|
+
return workflow.run(event, wrappedStep);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=workflow-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-coordinator.js","sourceRoot":"","sources":["../src/workflow-coordinator.ts"],"names":[],"mappings":"AAAA;qEACqE;AACrE,MAAM,UAAU,yBAAyB,CAAC,SAAiB,EAAE,QAAkB;IAC7E,OAAO;;WAEE,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA2BK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;CAchD,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const LOCAL_WORKFLOW_HOST = "import {WorkerEntrypoint,RpcTarget} from \"cloudflare:workers\";\nimport {createDynamicWorkflowEntrypoint,wrapWorkflowBinding} from \"@cloudflare/dynamic-workflows\";\nexport {DynamicWorkflowBinding} from \"@cloudflare/dynamic-workflows\";\nasync function physical(name,id){return \"local_\"+Array.from(new Uint8Array(await crypto.subtle.digest(\"SHA-256\",new TextEncoder().encode(name+\":\"+id))),b=>b.toString(16).padStart(2,\"0\")).join(\"\");}\nclass Instance extends RpcTarget {\n #native; #id;\n constructor(native,id){super();this.#native=native;this.#id=id;}\n get id(){return this.#id;}\n async status(){const result=await this.#native.status();return {id:this.#id,status:result.status,...(result.error?{error:{code:\"app_workflow_execution_failed\"}}:{})};}\n sendEvent(event){return this.#native.sendEvent(event);}\n pause(){return this.#native.pause();} resume(){return this.#native.resume();} terminate(){return this.#native.terminate();} restart(){return this.#native.restart();}\n}\nexport class AppWorkflowBinding extends WorkerEntrypoint {\n async create(options={}) {const id=options.id??crypto.randomUUID();const native=await wrapWorkflowBinding({name:this.ctx.props.name,localId:id}).create({id:await physical(this.ctx.props.name,id),params:options.params??{}});return new Instance(native,id);}\n async get(id){return new Instance(await this.env.WORKFLOWS.get(await physical(this.ctx.props.name,id)),id);}\n async createBatch(items){const results=[];for(const item of items){try{const run=await this.create(item);results.push({id:await run.id,accepted:true});}catch{results.push({id:item.id,accepted:false,error:\"app_workflow_operation_failed\"});}}return results;}\n}\nclass Services extends RpcTarget {\n #env; #names;\n constructor(env,names){super();this.#env=env;this.#names=names;}\n async observeStep() {}\n invoke(name,request){if(!this.#names.includes(name))throw new Error(\"app_workflow_service_not_authorized\");return this.#env[name].fetch(request);}\n}\nexport const DynamicWorkflow=createDynamicWorkflowEntrypoint(async({env,metadata})=>{\n const config=JSON.parse(env.CONFIG),declaration=config.artifact.declarations.find(d=>d.name===metadata.name);\n if(!declaration)throw new Error(\"app_workflow_scope_invalid\");\n // Match hosted public Internet access; never inherit the host's env/bindings.\n const worker=env.LOADER.get(\"public-internet-v1:\"+config.artifact.module.sha256+\":\"+declaration.name,()=>({compatibilityDate:config.artifact.compatibilityDate,compatibilityFlags:config.artifact.compatibilityFlags,\n mainModule:\"coordinator.mjs\",modules:{\"coordinator.mjs\":{js:config.wrappers[declaration.name]},\"workflow.mjs\":{js:config.code}},env:config.artifact.vars,limits:{cpuMs:50,subRequests:50}}));\n return {run(event,step){return worker.getEntrypoint(\"AndeoCoordinator\").run({...event,instanceId:metadata.localId},step,new Services(env,config.artifact.services));}};\n});\nexport default {fetch(){return new Response(\"Not found\",{status:404});}};";
|
|
2
|
+
//# sourceMappingURL=workflow-dev-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-dev-host.d.ts","sourceRoot":"","sources":["../src/workflow-dev-host.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,mBAAmB,i9FA+B0C,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Local-only host: real Cloudflare execution primitives, not hosted policy.
|
|
2
|
+
export const LOCAL_WORKFLOW_HOST = `import {WorkerEntrypoint,RpcTarget} from "cloudflare:workers";
|
|
3
|
+
import {createDynamicWorkflowEntrypoint,wrapWorkflowBinding} from "@cloudflare/dynamic-workflows";
|
|
4
|
+
export {DynamicWorkflowBinding} from "@cloudflare/dynamic-workflows";
|
|
5
|
+
async function physical(name,id){return "local_"+Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(name+":"+id))),b=>b.toString(16).padStart(2,"0")).join("");}
|
|
6
|
+
class Instance extends RpcTarget {
|
|
7
|
+
#native; #id;
|
|
8
|
+
constructor(native,id){super();this.#native=native;this.#id=id;}
|
|
9
|
+
get id(){return this.#id;}
|
|
10
|
+
async status(){const result=await this.#native.status();return {id:this.#id,status:result.status,...(result.error?{error:{code:"app_workflow_execution_failed"}}:{})};}
|
|
11
|
+
sendEvent(event){return this.#native.sendEvent(event);}
|
|
12
|
+
pause(){return this.#native.pause();} resume(){return this.#native.resume();} terminate(){return this.#native.terminate();} restart(){return this.#native.restart();}
|
|
13
|
+
}
|
|
14
|
+
export class AppWorkflowBinding extends WorkerEntrypoint {
|
|
15
|
+
async create(options={}) {const id=options.id??crypto.randomUUID();const native=await wrapWorkflowBinding({name:this.ctx.props.name,localId:id}).create({id:await physical(this.ctx.props.name,id),params:options.params??{}});return new Instance(native,id);}
|
|
16
|
+
async get(id){return new Instance(await this.env.WORKFLOWS.get(await physical(this.ctx.props.name,id)),id);}
|
|
17
|
+
async createBatch(items){const results=[];for(const item of items){try{const run=await this.create(item);results.push({id:await run.id,accepted:true});}catch{results.push({id:item.id,accepted:false,error:"app_workflow_operation_failed"});}}return results;}
|
|
18
|
+
}
|
|
19
|
+
class Services extends RpcTarget {
|
|
20
|
+
#env; #names;
|
|
21
|
+
constructor(env,names){super();this.#env=env;this.#names=names;}
|
|
22
|
+
async observeStep() {}
|
|
23
|
+
invoke(name,request){if(!this.#names.includes(name))throw new Error("app_workflow_service_not_authorized");return this.#env[name].fetch(request);}
|
|
24
|
+
}
|
|
25
|
+
export const DynamicWorkflow=createDynamicWorkflowEntrypoint(async({env,metadata})=>{
|
|
26
|
+
const config=JSON.parse(env.CONFIG),declaration=config.artifact.declarations.find(d=>d.name===metadata.name);
|
|
27
|
+
if(!declaration)throw new Error("app_workflow_scope_invalid");
|
|
28
|
+
// Match hosted public Internet access; never inherit the host's env/bindings.
|
|
29
|
+
const worker=env.LOADER.get("public-internet-v1:"+config.artifact.module.sha256+":"+declaration.name,()=>({compatibilityDate:config.artifact.compatibilityDate,compatibilityFlags:config.artifact.compatibilityFlags,
|
|
30
|
+
mainModule:"coordinator.mjs",modules:{"coordinator.mjs":{js:config.wrappers[declaration.name]},"workflow.mjs":{js:config.code}},env:config.artifact.vars,limits:{cpuMs:50,subRequests:50}}));
|
|
31
|
+
return {run(event,step){return worker.getEntrypoint("AndeoCoordinator").run({...event,instanceId:metadata.localId},step,new Services(env,config.artifact.services));}};
|
|
32
|
+
});
|
|
33
|
+
export default {fetch(){return new Response("Not found",{status:404});}};`;
|
|
34
|
+
//# sourceMappingURL=workflow-dev-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-dev-host.js","sourceRoot":"","sources":["../src/workflow-dev-host.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0EA+BuC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Miniflare } from "miniflare";
|
|
2
|
+
/** Real Workflow, Loader and RPC execution with explicitly mapped local
|
|
3
|
+
* services. Hosted authorization/WfP routing still require hosted verification. */
|
|
4
|
+
export declare function startWorkflowDev(root: string, directory: string, port?: number): Promise<Miniflare>;
|
|
5
|
+
//# sourceMappingURL=workflow-dev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-dev.d.ts","sourceRoot":"","sources":["../src/workflow-dev.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAqC,MAAM,WAAW,CAAC;AASzE;mFACmF;AACnF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,SAAO,sBAsElF"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { build } from "esbuild";
|
|
2
|
+
import { readFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import { resolve, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseEnv } from "node:util";
|
|
6
|
+
import { Miniflare, Log, LogLevel } from "miniflare";
|
|
7
|
+
import { verifyArtifact } from "./artifact.js";
|
|
8
|
+
import { renderWorkflowCoordinator } from "./workflow-coordinator.js";
|
|
9
|
+
import { workflowRecord } from "./workflow-contract.js";
|
|
10
|
+
import { readBoundedFile } from "./files.js";
|
|
11
|
+
import { LOCAL_WORKFLOW_HOST } from "./workflow-dev-host.js";
|
|
12
|
+
/** Real Workflow, Loader and RPC execution with explicitly mapped local
|
|
13
|
+
* services. Hosted authorization/WfP routing still require hosted verification. */
|
|
14
|
+
export async function startWorkflowDev(root, directory, port = 8787) {
|
|
15
|
+
const artifact = await verifyArtifact(directory), workflows = artifact.envelope.manifest.workflows;
|
|
16
|
+
if (!workflows)
|
|
17
|
+
throw new Error("app_workflow_declaration_required");
|
|
18
|
+
let selected = {};
|
|
19
|
+
if (workflows.services.length) {
|
|
20
|
+
let value;
|
|
21
|
+
try {
|
|
22
|
+
value = JSON.parse(new TextDecoder().decode(await readBoundedFile(resolve(root, "andeo.workflow-dev.json"), 16384)));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new Error("Define local service artifact directories in andeo.workflow-dev.json before starting workflow development.");
|
|
26
|
+
}
|
|
27
|
+
if (!workflowRecord(value) || Object.values(value).some(path => typeof path !== "string"))
|
|
28
|
+
throw new Error("app_workflow_dev_services_invalid");
|
|
29
|
+
selected = value;
|
|
30
|
+
if (workflows.services.some(name => !selected[name]))
|
|
31
|
+
throw new Error("app_workflow_dev_service_missing");
|
|
32
|
+
}
|
|
33
|
+
const worker = (name, env, source, compatibilityDate, assets) => ({ config: {
|
|
34
|
+
type: "worker", name, compatibilityDate, compatibilityFlags: ["nodejs_compat"], env,
|
|
35
|
+
manifest: { mainModule: "index.mjs", modulesRoot: root, modules: { "index.mjs": { type: "esm", contents: source } } },
|
|
36
|
+
...(assets ? { assets: { directory: assets, runWorkerFirst: true, hasUserWorker: true } } : {}),
|
|
37
|
+
} });
|
|
38
|
+
const text = (value) => ({ type: "text", value });
|
|
39
|
+
async function appEnv(appDirectory, scope) {
|
|
40
|
+
const { envelope: { manifest } } = await verifyArtifact(appDirectory);
|
|
41
|
+
const bindings = Object.fromEntries(Object.entries(manifest.vars ?? {}).map(([name, value]) => [name, text(String(value))]));
|
|
42
|
+
if (manifest.secrets?.length) {
|
|
43
|
+
let secrets;
|
|
44
|
+
try {
|
|
45
|
+
secrets = parseEnv(await readFile(resolve(appDirectory, ".dev.vars"), "utf8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
throw new Error("Put local-only declared secrets in .dev.vars beside its artifact. Secret values are never printed.");
|
|
49
|
+
}
|
|
50
|
+
for (const name of manifest.secrets) {
|
|
51
|
+
if (!(name in secrets))
|
|
52
|
+
throw new Error("app_workflow_dev_secret_missing");
|
|
53
|
+
bindings[name] = text(secrets[name]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const resource of manifest.resources) {
|
|
57
|
+
if (!workflowRecord(resource) || typeof resource.name !== "string")
|
|
58
|
+
throw new Error("app_workflow_dev_resource_invalid");
|
|
59
|
+
if (resource.type === "d1")
|
|
60
|
+
bindings[resource.name] = { type: "d1", id: `${scope}-${resource.name}` };
|
|
61
|
+
else if (resource.type === "kv")
|
|
62
|
+
bindings[resource.name] = { type: "kv", id: `${scope}-${resource.name}` };
|
|
63
|
+
else if (resource.type === "r2")
|
|
64
|
+
bindings[resource.name] = { type: "r2", name: `${scope}-${resource.name}` };
|
|
65
|
+
else
|
|
66
|
+
throw new Error("app_workflow_dev_resource_unsupported");
|
|
67
|
+
}
|
|
68
|
+
for (const service of manifest.services) {
|
|
69
|
+
if (!workflowRecord(service) || typeof service.name !== "string" || !selected[service.name])
|
|
70
|
+
throw new Error("app_workflow_dev_service_missing");
|
|
71
|
+
bindings[service.name] = { type: "worker", worker: `service-${service.name}` };
|
|
72
|
+
}
|
|
73
|
+
if (manifest.files.length)
|
|
74
|
+
bindings.ASSETS = { type: "assets" };
|
|
75
|
+
return bindings;
|
|
76
|
+
}
|
|
77
|
+
const appBindings = await appEnv(directory, "app");
|
|
78
|
+
for (const declaration of workflows.declarations)
|
|
79
|
+
appBindings[declaration.binding] = {
|
|
80
|
+
type: "worker", worker: "workflow-host", exportName: "AppWorkflowBinding", props: { name: declaration.name },
|
|
81
|
+
};
|
|
82
|
+
const hostEnv = { LOADER: { type: "worker-loader" }, WORKFLOWS: { type: "workflow", name: "andeo-local-workflows", worker: "workflow-host", exportName: "DynamicWorkflow" },
|
|
83
|
+
CONFIG: text(JSON.stringify({ artifact: workflows, code: await readFile(resolve(directory, "workflow.mjs"), "utf8"),
|
|
84
|
+
wrappers: Object.fromEntries(workflows.declarations.map(d => [d.name, renderWorkflowCoordinator(d.class_name, workflows.services)])) })),
|
|
85
|
+
};
|
|
86
|
+
const workers = [worker("app", appBindings, await readFile(resolve(directory, "worker.mjs"), "utf8"), String(artifact.envelope.manifest.runtime.compatibilityDate), artifact.envelope.manifest.files.length ? resolve(directory, "assets") : undefined)];
|
|
87
|
+
for (const [name, path] of Object.entries(selected)) {
|
|
88
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(name))
|
|
89
|
+
throw new Error("app_workflow_dev_service_invalid");
|
|
90
|
+
const target = resolve(root, path), service = await verifyArtifact(target);
|
|
91
|
+
if (service.envelope.manifest.workflows)
|
|
92
|
+
throw new Error("Start one workflow application at a time in local development.");
|
|
93
|
+
workers.push(worker(`service-${name}`, await appEnv(target, `service-${name}`), await readFile(resolve(target, "worker.mjs"), "utf8"), String(service.envelope.manifest.runtime.compatibilityDate), service.envelope.manifest.files.length ? resolve(target, "assets") : undefined));
|
|
94
|
+
hostEnv[name] = { type: "worker", worker: `service-${name}` };
|
|
95
|
+
}
|
|
96
|
+
const host = (await build({ stdin: { contents: LOCAL_WORKFLOW_HOST, resolveDir: dirname(fileURLToPath(import.meta.url)) },
|
|
97
|
+
bundle: true, format: "esm", platform: "neutral", write: false, external: ["cloudflare:*", "node:*"] })).outputFiles[0].text;
|
|
98
|
+
workers.push(worker("workflow-host", hostEnv, host, workflows.compatibilityDate));
|
|
99
|
+
const state = resolve(root, ".tender/workflows-local");
|
|
100
|
+
await mkdir(state, { recursive: true });
|
|
101
|
+
const runtime = new Miniflare({ host: "127.0.0.1", port, cf: false, telemetry: { enabled: false }, log: new Log(LogLevel.WARN), logRequests: false,
|
|
102
|
+
resourcePersistencePath: state, resourceTmpPath: resolve(state, "tmp"), workers });
|
|
103
|
+
try {
|
|
104
|
+
await runtime.ready;
|
|
105
|
+
return runtime;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
await runtime.dispose();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=workflow-dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-dev.js","sourceRoot":"","sources":["../src/workflow-dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Runs only in the app's build process/sandbox, never in the control plane.
|
|
2
|
+
* The producer still owns compilation; split its compiled, portable module.
|
|
3
|
+
* esbuild inspects exports without executing merchant imports. */
|
|
4
|
+
export declare function packageAppWorkflows(root: string, artifactDirectory: string, environment?: string): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=workflow-package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-package.d.ts","sourceRoot":"","sources":["../src/workflow-package.ts"],"names":[],"mappings":"AAUA;;kEAEkE;AAClE,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiGtH"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { build } from "esbuild";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { writeFile } from "node:fs/promises";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { verifyArtifact } from "./artifact.js";
|
|
6
|
+
import { readWorkflowConfig } from "./workflow-config.js";
|
|
7
|
+
import { parseWorkflowArtifact } from "./workflow-contract.js";
|
|
8
|
+
import { readBoundedFile } from "./files.js";
|
|
9
|
+
import { MAX_WORKER_BUNDLE_BYTES } from "./artifact-limits.js";
|
|
10
|
+
/** Runs only in the app's build process/sandbox, never in the control plane.
|
|
11
|
+
* The producer still owns compilation; split its compiled, portable module.
|
|
12
|
+
* esbuild inspects exports without executing merchant imports. */
|
|
13
|
+
export async function packageAppWorkflows(root, artifactDirectory, environment) {
|
|
14
|
+
const config = await readWorkflowConfig(root, environment);
|
|
15
|
+
if (!config?.declarations.length)
|
|
16
|
+
return;
|
|
17
|
+
const verified = await verifyArtifact(artifactDirectory);
|
|
18
|
+
const vars = Object.fromEntries(Object.keys(config.vars).map(name => {
|
|
19
|
+
const values = verified.envelope.manifest.vars;
|
|
20
|
+
const value = values && typeof values === "object" ? values[name] : undefined;
|
|
21
|
+
if (typeof value !== "string")
|
|
22
|
+
throw new Error("app_workflow_vars_must_match_artifact");
|
|
23
|
+
return [name, value];
|
|
24
|
+
}));
|
|
25
|
+
if (verified.envelope.manifest.workflows) {
|
|
26
|
+
const retained = verified.envelope.manifest.workflows;
|
|
27
|
+
if (JSON.stringify(retained.declarations) !== JSON.stringify(config.declarations)
|
|
28
|
+
|| retained.compatibilityDate !== config.compatibilityDate
|
|
29
|
+
|| JSON.stringify(Object.entries(retained.vars).sort()) !== JSON.stringify(Object.entries(vars).sort())) {
|
|
30
|
+
throw new Error("app_workflow_declaration_mismatch");
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const { envelope } = verified;
|
|
35
|
+
const source = new TextDecoder("utf8", { fatal: true }).decode(await readBoundedFile(resolve(artifactDirectory, "worker.mjs"), MAX_WORKER_BUNDLE_BYTES));
|
|
36
|
+
const services = envelope.manifest.services.map(value => {
|
|
37
|
+
if (!value || typeof value !== "object" || !("name" in value) || typeof value.name !== "string")
|
|
38
|
+
throw new Error("app_workflow_services_invalid");
|
|
39
|
+
return value.name;
|
|
40
|
+
}).sort();
|
|
41
|
+
const occupied = new Set([
|
|
42
|
+
...services, ...(envelope.manifest.secrets ?? []), ...Object.keys(config.vars),
|
|
43
|
+
...envelope.manifest.resources.map(value => value && typeof value === "object" && "name" in value ? value.name : ""),
|
|
44
|
+
]);
|
|
45
|
+
if (config.declarations.some(d => occupied.has(d.binding)))
|
|
46
|
+
throw new Error("app_workflow_binding_collision");
|
|
47
|
+
const classes = [...new Set(config.declarations.map(d => d.class_name))];
|
|
48
|
+
const compile = (contents, outfile) => build({
|
|
49
|
+
stdin: { contents, sourcefile: "andeo-entry.mjs", resolveDir: root },
|
|
50
|
+
bundle: true, format: "esm", platform: "neutral", target: "es2022", write: false, metafile: true,
|
|
51
|
+
treeShaking: true, sourcemap: "external", outfile, external: ["cloudflare:*", "node:*"],
|
|
52
|
+
plugins: [{ name: "retained-app", setup(builder) {
|
|
53
|
+
builder.onResolve({ filter: /^andeo-retained-app$/ }, () => ({ path: "merchant.mjs", namespace: "andeo" }));
|
|
54
|
+
builder.onLoad({ filter: /.*/, namespace: "andeo" }, () => ({ contents: source, loader: "js", resolveDir: root }));
|
|
55
|
+
} }],
|
|
56
|
+
});
|
|
57
|
+
const inspected = await compile(source, "inspect.mjs");
|
|
58
|
+
const exports = Object.values(inspected.metafile.outputs).flatMap(output => output.exports);
|
|
59
|
+
if (!exports.includes("default") || classes.some(name => !exports.includes(name)))
|
|
60
|
+
throw new Error("app_workflow_export_missing");
|
|
61
|
+
const httpExports = exports.filter(name => !classes.includes(name));
|
|
62
|
+
// Quote export names safely, including non-identifier module export names.
|
|
63
|
+
const http = await compile("export { " + httpExports.map(name => JSON.stringify(name)).join(",") + ' } from "andeo-retained-app";', "worker.mjs");
|
|
64
|
+
const coordinator = await compile("export { " + classes.join(",") + ' } from "andeo-retained-app";', "workflow.mjs");
|
|
65
|
+
const httpBytes = http.outputFiles.find(file => file.path.endsWith("/worker.mjs")).contents;
|
|
66
|
+
const code = coordinator.outputFiles.find(file => file.path.endsWith("/workflow.mjs")).contents;
|
|
67
|
+
const map = coordinator.outputFiles.find(file => file.path.endsWith("/workflow.mjs.map")).contents;
|
|
68
|
+
const descriptor = (path, bytes) => ({ path, sha256: hash(bytes), bytes: bytes.byteLength });
|
|
69
|
+
const workflows = parseWorkflowArtifact({
|
|
70
|
+
schema: "andeo.app-workflows/v1", declarations: config.declarations,
|
|
71
|
+
module: { ...descriptor("workflow.mjs", code), contentType: "application/javascript+module" },
|
|
72
|
+
sourceMap: descriptor("workflow.mjs.map", map), compatibilityDate: config.compatibilityDate,
|
|
73
|
+
compatibilityFlags: ["nodejs_compat"], vars, services,
|
|
74
|
+
});
|
|
75
|
+
envelope.manifest.module = { ...descriptor("worker.mjs", httpBytes), path: "worker.mjs", contentType: "application/javascript+module" };
|
|
76
|
+
envelope.manifest.workflows = workflows;
|
|
77
|
+
const appVars = envelope.manifest.vars;
|
|
78
|
+
if (Object.entries(vars).some(([name, value]) => !appVars || typeof appVars !== "object" || appVars[name] !== value)) {
|
|
79
|
+
throw new Error("app_workflow_vars_must_match_artifact");
|
|
80
|
+
}
|
|
81
|
+
envelope.bundleDigest = hash(new TextEncoder().encode(JSON.stringify({
|
|
82
|
+
module: envelope.manifest.module, files: envelope.manifest.files,
|
|
83
|
+
...(envelope.manifest.databaseSchema === undefined ? {} : { databaseSchema: envelope.manifest.databaseSchema }),
|
|
84
|
+
workflows,
|
|
85
|
+
})));
|
|
86
|
+
envelope.manifest.runtime.assetPrefix = "/_tenant-artifacts/" + envelope.bundleDigest;
|
|
87
|
+
await writeFile(resolve(artifactDirectory, "worker.mjs"), httpBytes);
|
|
88
|
+
await writeFile(resolve(artifactDirectory, "workflow.mjs"), code);
|
|
89
|
+
await writeFile(resolve(artifactDirectory, "workflow.mjs.map"), map);
|
|
90
|
+
await writeFile(verified.envelopePath, JSON.stringify(envelope, null, 2) + "\n");
|
|
91
|
+
const appTypes = config.declarations.map(d => " " + d.binding + ": AndeoWorkflowBinding;").join("\n");
|
|
92
|
+
const coordinatorTypes = [...Object.keys(config.vars).map(name => " " + name + ": string;"),
|
|
93
|
+
...services.map(name => " " + name + ": Pick<Fetcher, 'fetch'>;")].join("\n");
|
|
94
|
+
await writeFile(resolve(artifactDirectory, "workflow-env.d.ts"), `// Generated; coordinator bindings intentionally exclude native secrets/resources.
|
|
95
|
+
interface AndeoWorkflowInstance {
|
|
96
|
+
readonly id: string | Promise<string>;
|
|
97
|
+
status(): Promise<{ status: string; error?: { code: string } }>;
|
|
98
|
+
sendEvent(event: { type: string; payload: unknown }): Promise<void>;
|
|
99
|
+
pause(): Promise<void>; resume(): Promise<void>; terminate(): Promise<void>; restart(): Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
interface AndeoWorkflowBinding {
|
|
102
|
+
create(options?: { id?: string; params?: unknown }): Promise<AndeoWorkflowInstance>;
|
|
103
|
+
get(id: string): Promise<AndeoWorkflowInstance>;
|
|
104
|
+
createBatch(options: { id?: string; params?: unknown }[]): Promise<({ id: string; accepted: true } | { id?: string; accepted: false; error: string })[]>;
|
|
105
|
+
}
|
|
106
|
+
interface AppWorkflowEnv {
|
|
107
|
+
${appTypes}
|
|
108
|
+
}
|
|
109
|
+
interface CoordinatorEnv {
|
|
110
|
+
${coordinatorTypes}
|
|
111
|
+
}
|
|
112
|
+
`);
|
|
113
|
+
await verifyArtifact(artifactDirectory);
|
|
114
|
+
}
|
|
115
|
+
function hash(bytes) { return createHash("sha256").update(bytes).digest("hex"); }
|
|
116
|
+
//# sourceMappingURL=workflow-package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-package.js","sourceRoot":"","sources":["../src/workflow-package.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@withandeo/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Developer CLI for Andeo applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -31,6 +31,13 @@
|
|
|
31
31
|
"typescript": "^7.0.2",
|
|
32
32
|
"vitest": "^4.1.11"
|
|
33
33
|
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@cloudflare/dynamic-workflows": "0.1.1",
|
|
36
|
+
"esbuild": "0.28.1",
|
|
37
|
+
"jsonc-parser": "3.3.1",
|
|
38
|
+
"miniflare": "5.20260918.0-alpha",
|
|
39
|
+
"smol-toml": "1.8.0"
|
|
40
|
+
},
|
|
34
41
|
"exports": {
|
|
35
42
|
"./cli": "./dist/main.js"
|
|
36
43
|
},
|
|
@@ -354,12 +354,25 @@ Retry only a requested or failed preview workflow:
|
|
|
354
354
|
npx @withandeo/cli delivery retry --delivery <delivery-id> --json
|
|
355
355
|
```
|
|
356
356
|
|
|
357
|
+
CLI 0.12.0 carries artifact/delivery access across automatic token refresh within
|
|
358
|
+
the same login. Logout, session expiry, or revoked owner/project access still
|
|
359
|
+
stop background work. For a pre-session-tracking preview stranded by an expired
|
|
360
|
+
credential, only its original owner may explicitly recover it from the linked
|
|
361
|
+
app with `delivery retry --delivery <delivery-id> --reauthorize --json`. This
|
|
362
|
+
requires current developer access, retains the exact artifact and upload
|
|
363
|
+
receipts, and cannot replace an already tracked login or publish production.
|
|
364
|
+
Do not clear pending provider holds or rewrite credential IDs to recover work.
|
|
365
|
+
|
|
357
366
|
Mint a new browser session for an already-succeeded delivery without rebuilding:
|
|
358
367
|
|
|
359
368
|
```sh
|
|
360
|
-
npx @withandeo/cli
|
|
369
|
+
npx @withandeo/cli preview entries --json
|
|
370
|
+
npx @withandeo/cli preview open --from <delivery-id> --json
|
|
371
|
+
npx @withandeo/cli preview open --from sbl_EXAMPLE --return-path /account --json
|
|
361
372
|
```
|
|
362
373
|
|
|
374
|
+
Preview entry selection follows published app connections automatically. When the response requires a choice, select an eligible app using `--through prj_ENTRY`. Only the previewed app's developer grant is needed. Private apps cannot open directly; a connection administrator must enable an eligible entry. Preserve the exact `from` ID when recovering from a session error and use `preview open` instead of rebuilding. Opening replaces the browser's previous preview selection and preserves sign-in.
|
|
375
|
+
|
|
363
376
|
`<delivery-id>` is the `dly_` value returned by `preview`. A `dwf_` value is a production workflow ID and must not be passed to developer-delivery commands. If a merchant administrator sees a `dwf_` publish waiting with zero attempts, the supported recovery is **Activity → Resume exact publish**; it resumes the stored exact composition without rebuilding. Use the error code, request ID, and suggested command from the CLI. Do not retry with altered IDs, another project, or raw HTTP requests.
|
|
364
377
|
|
|
365
378
|
When runtime evidence is needed, stream only the linked project and exact target:
|
|
@@ -9,3 +9,5 @@ Local HTTP development returns an explicit signed-out state. Real Shopify sign-i
|
|
|
9
9
|
The generated `.dev` hostname stays the Shopify callback anchor. When a merchant vanity domain is activated, add it to the public comma-separated `ACCOUNT_VANITY_HOSTNAMES` environment value so the exact-host session policy can safely return the shopper there. Do not move Shopify callback configuration to the vanity hostname.
|
|
10
10
|
|
|
11
11
|
Managed builds retain published settings through `TENDER_PUBLIC_VARS_SOURCE`, which points to the app's verified build envelope and takes precedence over `--vars`. The packager checks the app identity and declared public-variable allowlist. Without that input, local packaging reads `--vars` or `.dev.vars` as usual.
|
|
12
|
+
|
|
13
|
+
If this app needs runtime secrets, declare their names in its app configuration and ask an app administrator to select shared previews, initialize its targets, and save each app-level secret in Settings. Read a native secret directly as a string, such as `env.API_TOKEN`; do not use a Secrets Store `.get()` binding. One saved value applies to preview and production. A new gateway preview replaces its previous preview. The portal can keep independent previews so multiple portal PRs remain available simultaneously. These are explicit project policies, independent of the app's name or kind.
|