@boardwalk-labs/cli 0.1.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.
Files changed (73) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +110 -0
  3. package/bin/boardwalk.js +4 -0
  4. package/dist/artifact.d.ts +53 -0
  5. package/dist/artifact.js +267 -0
  6. package/dist/artifact.js.map +1 -0
  7. package/dist/auth/discovery.d.ts +8 -0
  8. package/dist/auth/discovery.js +43 -0
  9. package/dist/auth/discovery.js.map +1 -0
  10. package/dist/auth/login.d.ts +13 -0
  11. package/dist/auth/login.js +74 -0
  12. package/dist/auth/login.js.map +1 -0
  13. package/dist/auth/pkce.d.ts +63 -0
  14. package/dist/auth/pkce.js +197 -0
  15. package/dist/auth/pkce.js.map +1 -0
  16. package/dist/auth/resolve.d.ts +12 -0
  17. package/dist/auth/resolve.js +51 -0
  18. package/dist/auth/resolve.js.map +1 -0
  19. package/dist/bundle.d.ts +35 -0
  20. package/dist/bundle.js +176 -0
  21. package/dist/bundle.js.map +1 -0
  22. package/dist/client.d.ts +65 -0
  23. package/dist/client.js +193 -0
  24. package/dist/client.js.map +1 -0
  25. package/dist/commands/cancel.d.ts +14 -0
  26. package/dist/commands/cancel.js +53 -0
  27. package/dist/commands/cancel.js.map +1 -0
  28. package/dist/commands/check.d.ts +7 -0
  29. package/dist/commands/check.js +34 -0
  30. package/dist/commands/check.js.map +1 -0
  31. package/dist/commands/deploy.d.ts +15 -0
  32. package/dist/commands/deploy.js +56 -0
  33. package/dist/commands/deploy.js.map +1 -0
  34. package/dist/commands/dev.d.ts +14 -0
  35. package/dist/commands/dev.js +128 -0
  36. package/dist/commands/dev.js.map +1 -0
  37. package/dist/commands/init.d.ts +12 -0
  38. package/dist/commands/init.js +171 -0
  39. package/dist/commands/init.js.map +1 -0
  40. package/dist/commands/run.d.ts +32 -0
  41. package/dist/commands/run.js +105 -0
  42. package/dist/commands/run.js.map +1 -0
  43. package/dist/commands/session.d.ts +13 -0
  44. package/dist/commands/session.js +58 -0
  45. package/dist/commands/session.js.map +1 -0
  46. package/dist/config.d.ts +14 -0
  47. package/dist/config.js +64 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/credentials.d.ts +23 -0
  50. package/dist/credentials.js +69 -0
  51. package/dist/credentials.js.map +1 -0
  52. package/dist/deployment.d.ts +44 -0
  53. package/dist/deployment.js +100 -0
  54. package/dist/deployment.js.map +1 -0
  55. package/dist/dev/host.d.ts +16 -0
  56. package/dist/dev/host.js +76 -0
  57. package/dist/dev/host.js.map +1 -0
  58. package/dist/errors.d.ts +8 -0
  59. package/dist/errors.js +18 -0
  60. package/dist/errors.js.map +1 -0
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.js +147 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/manifest.d.ts +12 -0
  65. package/dist/manifest.js +64 -0
  66. package/dist/manifest.js.map +1 -0
  67. package/dist/project.d.ts +15 -0
  68. package/dist/project.js +79 -0
  69. package/dist/project.js.map +1 -0
  70. package/dist/render/renderer.d.ts +18 -0
  71. package/dist/render/renderer.js +108 -0
  72. package/dist/render/renderer.js.map +1 -0
  73. package/package.json +56 -0
package/dist/client.js ADDED
@@ -0,0 +1,193 @@
1
+ // BoardwalkClient — a small hand-rolled REST client over Boardwalk's public platform API
2
+ // (deliberately no codegen client framework).
3
+ //
4
+ // Targets the workflow endpoints the deploy flow needs:
5
+ // GET /v1/orgs/:slug/workflows — list (resolve create-vs-update by name)
6
+ // POST /v1/orgs/:slug/workflows/artifact-upload-url — presign an upload for the program artifact
7
+ // POST /v1/orgs/:slug/workflows — create (body: { artifact })
8
+ // PATCH /v1/workflows/:id — update → new version (body: { artifact })
9
+ // POST /v1/runs/:id/cancel — cancel a queued or in-flight run (204)
10
+ //
11
+ // Deploy is artifact-based: the CLI builds a content-addressed program tarball, uploads it straight
12
+ // to object storage via a presigned PUT (the CLI holds no storage credentials), then finalizes the
13
+ // version with a reference the server re-reads + verifies.
14
+ //
15
+ // Auth is a Bearer token (a session token from `boardwalk login`, OR a `bwk_…` API key).
16
+ // The API accepts both on the same header.
17
+ import { randomUUID } from "node:crypto";
18
+ import { CliError } from "./errors.js";
19
+ const UNSAFE_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"]);
20
+ export class BoardwalkClient {
21
+ baseUrl;
22
+ token;
23
+ fetchImpl;
24
+ constructor(opts) {
25
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
26
+ this.token = opts.token;
27
+ this.fetchImpl = opts.fetchImpl ?? fetch;
28
+ }
29
+ async listWorkflows(orgSlug) {
30
+ const body = await this.request("GET", `/v1/orgs/${encodeURIComponent(orgSlug)}/workflows`);
31
+ const rows = Array.isArray(body.workflows) ? body.workflows : [];
32
+ return rows.filter(isWorkflowSummary);
33
+ }
34
+ async createWorkflow(orgSlug, artifact) {
35
+ return this.deployResult(await this.request("POST", `/v1/orgs/${encodeURIComponent(orgSlug)}/workflows`, {
36
+ artifact,
37
+ }));
38
+ }
39
+ async updateWorkflow(id, artifact) {
40
+ return this.deployResult(await this.request("PATCH", `/v1/workflows/${encodeURIComponent(id)}`, { artifact }));
41
+ }
42
+ /** Request a presigned PUT for a program artifact (the CLI then uploads the tarball directly). */
43
+ async getArtifactUploadUrl(orgSlug, input) {
44
+ const body = await this.request("POST", `/v1/orgs/${encodeURIComponent(orgSlug)}/workflows/artifact-upload-url`, input);
45
+ if (typeof body.uploadUrl !== "string" || typeof body.contentType !== "string") {
46
+ throw new CliError("The API returned an unexpected upload-url response shape.");
47
+ }
48
+ return { uploadUrl: body.uploadUrl, contentType: body.contentType };
49
+ }
50
+ /** Upload the artifact bytes straight to storage via the presigned PUT. The Content-Type MUST
51
+ * equal the one signed into the URL, or the store rejects the PUT. No auth header — the URL
52
+ * carries the signature. */
53
+ async uploadArtifact(uploadUrl, contentType, bytes) {
54
+ let res;
55
+ try {
56
+ res = await this.fetchImpl(uploadUrl, {
57
+ method: "PUT",
58
+ headers: { "Content-Type": contentType },
59
+ body: bytes,
60
+ });
61
+ }
62
+ catch (err) {
63
+ throw new CliError("Could not upload the program artifact to storage.", err instanceof Error ? err.message : undefined);
64
+ }
65
+ if (!res.ok) {
66
+ throw new CliError(`Artifact upload failed (${String(res.status)}).`, await safeText(res));
67
+ }
68
+ }
69
+ async triggerRun(orgSlug, workflowId, input) {
70
+ const path = `/v1/orgs/${encodeURIComponent(orgSlug)}/workflows/${encodeURIComponent(workflowId)}/runs`;
71
+ return this.runSummary(await this.request("POST", path, input === undefined ? {} : { input }));
72
+ }
73
+ async getRun(runId) {
74
+ return this.runSummary(await this.request("GET", `/v1/runs/${encodeURIComponent(runId)}`));
75
+ }
76
+ /**
77
+ * Cancel a run. Idempotent server-side (a terminal/already-cancelling run is a no-op); the
78
+ * endpoint resolves the org from the run id, so no org slug is needed. Returns 204 No Content.
79
+ */
80
+ async cancelRun(runId) {
81
+ await this.request("POST", `/v1/runs/${encodeURIComponent(runId)}/cancel`);
82
+ }
83
+ async request(method, path, body) {
84
+ const headers = {
85
+ Authorization: `Bearer ${this.token}`,
86
+ Accept: "application/json",
87
+ };
88
+ if (body !== undefined)
89
+ headers["Content-Type"] = "application/json";
90
+ if (UNSAFE_METHODS.has(method))
91
+ headers["Idempotency-Key"] = randomUUID();
92
+ const init = { method, headers };
93
+ if (body !== undefined)
94
+ init.body = JSON.stringify(body);
95
+ let res;
96
+ try {
97
+ res = await this.fetchImpl(`${this.baseUrl}${path}`, init);
98
+ }
99
+ catch (err) {
100
+ throw new CliError(`Could not reach the Boardwalk API at ${this.baseUrl}.`, err instanceof Error ? err.message : undefined);
101
+ }
102
+ const text = await res.text();
103
+ if (!res.ok) {
104
+ throw new CliError(`${method} ${path} failed (${String(res.status)}).`, apiErrorMessage(text, res.status), res.status);
105
+ }
106
+ if (text.length === 0)
107
+ return undefined;
108
+ try {
109
+ return JSON.parse(text);
110
+ }
111
+ catch {
112
+ throw new CliError(`The API returned a non-JSON response for ${method} ${path}.`);
113
+ }
114
+ }
115
+ deployResult(body) {
116
+ if (typeof body === "object" && body !== null) {
117
+ const b = body;
118
+ if (isWorkflowSummary(b.workflow) && isVersion(b.version)) {
119
+ return { workflow: b.workflow, version: b.version };
120
+ }
121
+ }
122
+ throw new CliError("The API returned an unexpected workflow response shape.");
123
+ }
124
+ runSummary(body) {
125
+ if (typeof body === "object" && body !== null) {
126
+ const run = body.run;
127
+ if (isRunSummary(run))
128
+ return run;
129
+ }
130
+ throw new CliError("The API returned an unexpected run response shape.");
131
+ }
132
+ }
133
+ function isWorkflowSummary(value) {
134
+ if (typeof value !== "object" || value === null)
135
+ return false;
136
+ const v = value;
137
+ return (typeof v.id === "string" &&
138
+ typeof v.name === "string" &&
139
+ (v.currentVersionId === null || typeof v.currentVersionId === "string"));
140
+ }
141
+ function isVersion(value) {
142
+ if (typeof value !== "object" || value === null)
143
+ return false;
144
+ const v = value;
145
+ return typeof v.id === "string" && typeof v.number === "number";
146
+ }
147
+ function isRunSummary(value) {
148
+ if (typeof value !== "object" || value === null)
149
+ return false;
150
+ const v = value;
151
+ return (typeof v.id === "string" &&
152
+ typeof v.workflowId === "string" &&
153
+ typeof v.status === "string" &&
154
+ (v.outcomeStatus === null || typeof v.outcomeStatus === "string") &&
155
+ (v.startedAt === null || typeof v.startedAt === "number") &&
156
+ (v.completedAt === null || typeof v.completedAt === "number"));
157
+ }
158
+ /** Best-effort read of a response body for an error message (never throws). */
159
+ async function safeText(res) {
160
+ try {
161
+ const t = await res.text();
162
+ return t.length > 0 ? t.slice(0, 300) : undefined;
163
+ }
164
+ catch {
165
+ return undefined;
166
+ }
167
+ }
168
+ /** Pull a human message out of the API's `{ error: { code, message } }` (or plain text) body. */
169
+ function apiErrorMessage(text, status) {
170
+ if (status === 401)
171
+ return "Unauthorized — run `boardwalk login`, or set BOARDWALK_API_KEY.";
172
+ if (status === 403)
173
+ return "Forbidden — your account lacks permission for this org.";
174
+ try {
175
+ const body = JSON.parse(text);
176
+ if (typeof body === "object" && body !== null) {
177
+ const err = body.error;
178
+ if (typeof err === "object" && err !== null) {
179
+ const message = err.message;
180
+ if (typeof message === "string" && message.length > 0)
181
+ return message;
182
+ }
183
+ const topMessage = body.message;
184
+ if (typeof topMessage === "string" && topMessage.length > 0)
185
+ return topMessage;
186
+ }
187
+ }
188
+ catch {
189
+ // not JSON
190
+ }
191
+ return text.length > 0 ? text.slice(0, 300) : "(no response body)";
192
+ }
193
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CliConfig } from "../config.js";
2
+ import type { FetchLike } from "../auth/pkce.js";
3
+ export interface CancelOptions {
4
+ runId: string;
5
+ token?: string | undefined;
6
+ }
7
+ export interface CancelDeps {
8
+ config: CliConfig;
9
+ fetchImpl?: FetchLike;
10
+ log?: (line: string) => void;
11
+ }
12
+ export declare function runCancel(opts: CancelOptions, deps: CancelDeps): Promise<void>;
13
+ /** Human-readable line describing a run's status right after a cancel request. */
14
+ export declare function cancelMessage(status: string, runId: string): string;
@@ -0,0 +1,53 @@
1
+ // `boardwalk cancel <runId>` — stop a queued or in-flight run.
2
+ //
3
+ // Thin front-end over POST /v1/runs/:id/cancel (idempotent server-side). The endpoint resolves the
4
+ // org from the run id, so no --org / project link is needed — just a run id + a token. After the
5
+ // cancel we read the run back to report what actually happened, since cancellation is async:
6
+ // • `cancelling` — a running worker is being signalled; it will finalize as `cancelled`.
7
+ // • `cancelled` — a queued/sleeping run flipped straight to terminal.
8
+ // • already terminal (`completed`/`failed`) — the cancel was a harmless no-op.
9
+ import { CliError } from "../errors.js";
10
+ import { CredentialStore } from "../credentials.js";
11
+ import { resolveToken } from "../auth/resolve.js";
12
+ import { BoardwalkClient } from "../client.js";
13
+ export async function runCancel(opts, deps) {
14
+ const log = deps.log ??
15
+ ((line) => {
16
+ console.log(line);
17
+ });
18
+ const runId = opts.runId.trim();
19
+ if (runId.length === 0) {
20
+ throw new CliError("A run id is required.", "Usage: boardwalk cancel <runId>");
21
+ }
22
+ const store = CredentialStore.atConfigDir(deps.config.configDir);
23
+ const token = await resolveToken({
24
+ config: deps.config,
25
+ store,
26
+ tokenFlag: opts.token,
27
+ ...(deps.fetchImpl !== undefined ? { fetchImpl: deps.fetchImpl } : {}),
28
+ });
29
+ const client = new BoardwalkClient({
30
+ baseUrl: deps.config.apiBaseUrl,
31
+ token,
32
+ ...(deps.fetchImpl !== undefined ? { fetchImpl: deps.fetchImpl } : {}),
33
+ });
34
+ await client.cancelRun(runId);
35
+ // Read the run back so we can report the resulting status (cancel is async + idempotent).
36
+ const run = await client.getRun(runId);
37
+ log(cancelMessage(run.status, runId));
38
+ }
39
+ /** Human-readable line describing a run's status right after a cancel request. */
40
+ export function cancelMessage(status, runId) {
41
+ switch (status) {
42
+ case "cancelled":
43
+ return `✓ run ${runId} cancelled.`;
44
+ case "cancelling":
45
+ return `… run ${runId} is cancelling — the worker is being stopped; it will finalize as cancelled.`;
46
+ case "completed":
47
+ case "failed":
48
+ return `• run ${runId} already finished (${status}) — nothing to cancel.`;
49
+ default:
50
+ return `… cancel requested for run ${runId} (status: ${status}).`;
51
+ }
52
+ }
53
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../src/commands/cancel.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,mGAAmG;AACnG,iGAAiG;AACjG,6FAA6F;AAC7F,2FAA2F;AAC3F,yEAAyE;AACzE,iFAAiF;AAEjF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAc/C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB,EAAE,IAAgB;IACnE,MAAM,GAAG,GACP,IAAI,CAAC,GAAG;QACR,CAAC,CAAC,IAAY,EAAQ,EAAE;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IAEL,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,iCAAiC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;QAC/B,KAAK;QACL,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAE9B,0FAA0F;IAC1F,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,KAAa;IACzD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW;YACd,OAAO,SAAS,KAAK,aAAa,CAAC;QACrC,KAAK,YAAY;YACf,OAAO,SAAS,KAAK,8EAA8E,CAAC;QACtG,KAAK,WAAW,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,SAAS,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;QAC5E;YACE,OAAO,8BAA8B,KAAK,aAAa,MAAM,IAAI,CAAC;IACtE,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface CheckOptions {
2
+ file: string;
3
+ }
4
+ export interface CheckDeps {
5
+ log?: (line: string) => void;
6
+ }
7
+ export declare function runCheck(opts: CheckOptions, deps?: CheckDeps): Promise<void>;
@@ -0,0 +1,34 @@
1
+ // `boardwalk check <file|dir>` — validate a workflow locally (no auth, no network).
2
+ //
3
+ // A fast pre-flight, all local:
4
+ // 1. extract the pure-literal `meta` and validate it against the FULL manifest schema — the
5
+ // same schema every engine enforces, so a green `check` means the manifest is the contract;
6
+ // 2. esbuild-bundle the program (proves it compiles, has no syntax errors, and that every
7
+ // non-SDK import resolves).
8
+ // Anything wrong throws a precise CliError before any deploy or run.
9
+ import { readFileSync } from "node:fs";
10
+ import { buildArtifact } from "../artifact.js";
11
+ import { resolveEntry } from "../bundle.js";
12
+ import { extractValidatedManifest } from "../manifest.js";
13
+ export async function runCheck(opts, deps = {}) {
14
+ const log = deps.log ??
15
+ ((line) => {
16
+ console.log(line);
17
+ });
18
+ // Validate the manifest from the author's ORIGINAL entry source (errors point at real lines).
19
+ const entry = resolveEntry(opts.file);
20
+ const manifest = extractValidatedManifest(readFileSync(entry, "utf8"), entry);
21
+ // Build the artifact (esbuild bundle + assets) — proves the program compiles end-to-end.
22
+ const artifact = await buildArtifact(opts.file);
23
+ const assets = artifact.assetPaths.length;
24
+ log(`✓ "${manifest.name}" is valid`);
25
+ log(` entry: ${artifact.entry}`);
26
+ log(` triggers: ${manifest.triggers.map((t) => t.kind).join(", ")}`);
27
+ if (manifest.secrets !== undefined && manifest.secrets.length > 0) {
28
+ log(` secrets: ${manifest.secrets.map((s) => s.name).join(", ")}`);
29
+ }
30
+ log(` artifact: ${String(artifact.size)} bytes (sha256 ${artifact.digest.slice(0, 12)}…)`);
31
+ if (assets > 0)
32
+ log(` assets: ${artifact.assetPaths.join(", ")}`);
33
+ }
34
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,EAAE;AACF,gCAAgC;AAChC,8FAA8F;AAC9F,iGAAiG;AACjG,4FAA4F;AAC5F,iCAAiC;AACjC,qEAAqE;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAU1D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAkB,EAAE,OAAkB,EAAE;IACrE,MAAM,GAAG,GACP,IAAI,CAAC,GAAG;QACR,CAAC,CAAC,IAAY,EAAQ,EAAE;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IAEL,8FAA8F;IAC9F,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IAE9E,yFAAyF;IACzF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;IAE1C,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,YAAY,CAAC,CAAC;IACrC,GAAG,CAAC,eAAe,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IACrC,GAAG,CAAC,eAAe,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,eAAe,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,GAAG,CAAC,eAAe,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5F,IAAI,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,eAAe,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { CliConfig } from "../config.js";
2
+ import type { FetchLike } from "../auth/pkce.js";
3
+ export interface DeployOptions {
4
+ file: string;
5
+ org?: string | undefined;
6
+ check: boolean;
7
+ /** Force esbuild bundling even for a single file (auto-on for a package directory). */
8
+ token?: string | undefined;
9
+ }
10
+ export interface DeployDeps {
11
+ config: CliConfig;
12
+ fetchImpl?: FetchLike;
13
+ log?: (line: string) => void;
14
+ }
15
+ export declare function runDeploy(opts: DeployOptions, deps: DeployDeps): Promise<void>;
@@ -0,0 +1,56 @@
1
+ // `boardwalk deploy <file|dir> [--org <slug>]` — ship a workflow program.
2
+ //
3
+ // Thin front-end over the REST create/update (which derives the manifest + reconciles triggers
4
+ // server-side). Identity is the project link (.boardwalk/project.json): once linked, --org is
5
+ // optional and the workflow is updated by id (rename-safe). `--dry-run` prints the plan only.
6
+ import { CredentialStore } from "../credentials.js";
7
+ import { resolveToken } from "../auth/resolve.js";
8
+ import { BoardwalkClient } from "../client.js";
9
+ import { deployWithLink, loadProgram, planDeploy } from "../deployment.js";
10
+ import { projectDirFor, readLink } from "../project.js";
11
+ export async function runDeploy(opts, deps) {
12
+ const log = deps.log ??
13
+ ((line) => {
14
+ console.log(line);
15
+ });
16
+ const prog = await loadProgram(opts.file);
17
+ const assets = prog.artifact.assetPaths.length;
18
+ log(` built ${prog.entry} (${String(prog.artifact.size)} bytes${assets > 0 ? `, ${String(assets)} asset${assets === 1 ? "" : "s"}` : ""})`);
19
+ const store = CredentialStore.atConfigDir(deps.config.configDir);
20
+ const token = await resolveToken({
21
+ config: deps.config,
22
+ store,
23
+ tokenFlag: opts.token,
24
+ ...(deps.fetchImpl !== undefined ? { fetchImpl: deps.fetchImpl } : {}),
25
+ });
26
+ const client = new BoardwalkClient({
27
+ baseUrl: deps.config.apiBaseUrl,
28
+ token,
29
+ ...(deps.fetchImpl !== undefined ? { fetchImpl: deps.fetchImpl } : {}),
30
+ });
31
+ if (opts.check) {
32
+ await printPlan(client, opts, prog, log);
33
+ return;
34
+ }
35
+ const dep = await deployWithLink(client, { orgSlug: opts.org, target: opts.file, prog });
36
+ if (dep.gitignoreUpdated)
37
+ log(" linked → .boardwalk/project.json (added .boardwalk/ to .gitignore)");
38
+ log(`✓ ${dep.outcome} "${prog.name}" version ${String(dep.versionNumber)} (${dep.workflowId})`);
39
+ }
40
+ /** Read-only preview of what `deploy` would do (no writes). */
41
+ async function printPlan(client, opts, prog, log) {
42
+ const link = readLink(projectDirFor(opts.file));
43
+ if (link !== null) {
44
+ log(`plan: UPDATE linked workflow ${link.workflowId} (org ${link.orgSlug}) → new version`);
45
+ return;
46
+ }
47
+ if (opts.org === undefined || opts.org.length === 0) {
48
+ log(`plan: CREATE "${prog.name}" (unlinked — pass --org to check for an existing match)`);
49
+ return;
50
+ }
51
+ const plan = planDeploy(await client.listWorkflows(opts.org), prog.name);
52
+ log(plan.action === "create"
53
+ ? `plan: CREATE "${prog.name}" in org ${opts.org}`
54
+ : `plan: ADOPT existing "${prog.name}" (${plan.workflowId ?? "?"}) → new version`);
55
+ }
56
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,8FAA8F;AAG9F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAiBxD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB,EAAE,IAAgB;IACnE,MAAM,GAAG,GACP,IAAI,CAAC,GAAG;QACR,CAAC,CAAC,IAAY,EAAQ,EAAE;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IAEL,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;IAC/C,GAAG,CACD,WAAW,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CACxI,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;QAC/B,KAAK;QACL,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,IAAI,GAAG,CAAC,gBAAgB;QACtB,GAAG,CAAC,sEAAsE,CAAC,CAAC;IAC9E,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,aAAa,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;AAClG,CAAC;AAED,+DAA+D;AAC/D,KAAK,UAAU,SAAS,CACtB,MAAuB,EACvB,IAAmB,EACnB,IAAqB,EACrB,GAA2B;IAE3B,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,GAAG,CAAC,gCAAgC,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,OAAO,iBAAiB,CAAC,CAAC;QAC3F,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,iBAAiB,IAAI,CAAC,IAAI,0DAA0D,CAAC,CAAC;QAC1F,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,GAAG,CACD,IAAI,CAAC,MAAM,KAAK,QAAQ;QACtB,CAAC,CAAC,iBAAiB,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,GAAG,EAAE;QAClD,CAAC,CAAC,yBAAyB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,UAAU,IAAI,GAAG,iBAAiB,CACpF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface DevOptions {
2
+ file: string;
3
+ input?: string | undefined;
4
+ envFile?: string | undefined;
5
+ verbose: boolean;
6
+ stream?: string | undefined;
7
+ }
8
+ export interface DevDeps {
9
+ /** Raw event-stream writer (defaults to process.stdout). */
10
+ write?: (text: string) => void;
11
+ /** SIGINT hook installer — injected so tests don't touch real process signals. */
12
+ onSigint?: (handler: () => void) => () => void;
13
+ }
14
+ export declare function runDev(opts: DevOptions, deps?: DevDeps): Promise<void>;
@@ -0,0 +1,128 @@
1
+ // `boardwalk dev <file|dir>` — run the workflow NOW, locally, no account.
2
+ //
3
+ // The tightest possible author loop: derive + validate the manifest (precise errors before
4
+ // anything runs), bundle the program, execute it in-process against the minimal dev host
5
+ // (secrets from .env, real sleeps, Phase/output events), and stream the run-event log through
6
+ // the channel-filtered renderer — the same flags and frames every engine speaks.
7
+ //
8
+ // Exit codes: 0 completed · 1 failed · 130 cancelled (Ctrl-C).
9
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10
+ import { tmpdir } from "node:os";
11
+ import { join } from "node:path";
12
+ import { pathToFileURL } from "node:url";
13
+ import { parseEnv } from "node:util";
14
+ import { installConfig, installHost, installInput, resetRuntime, takeDeclaredOutput, } from "@boardwalk-labs/workflow/runtime";
15
+ import { CliError } from "../errors.js";
16
+ import { bundleForDev, resolveEntry } from "../bundle.js";
17
+ import { extractValidatedManifest } from "../manifest.js";
18
+ import { projectDirFor } from "../project.js";
19
+ import { createDevHost } from "../dev/host.js";
20
+ import { createRenderer, parseChannels } from "../render/renderer.js";
21
+ import { parseInput } from "./run.js";
22
+ export async function runDev(opts, deps = {}) {
23
+ const write = deps.write ??
24
+ ((text) => {
25
+ process.stdout.write(text);
26
+ });
27
+ const channels = parseChannels({ verbose: opts.verbose, stream: opts.stream });
28
+ const renderer = createRenderer(channels, write);
29
+ // 1. Validate before anything runs — errors point at the author's real file.
30
+ const entry = resolveEntry(opts.file);
31
+ const manifest = extractValidatedManifest(readFileSync(entry, "utf8"), entry);
32
+ const input = parseInput(opts.input);
33
+ // 2. The local secret store: the project's env file (explicit --env must exist).
34
+ const projectDir = projectDirFor(opts.file);
35
+ const envPath = opts.envFile ?? join(projectDir, ".env");
36
+ const envVars = loadEnvFile(envPath, opts.envFile !== undefined);
37
+ // 3. The run-event emitter: a single dev turn, 1-based seq, rendered through the channel filter.
38
+ const runId = `dev-${Date.now().toString(36)}`;
39
+ let seq = 0;
40
+ const emit = (body) => {
41
+ seq += 1;
42
+ renderer.render({ ...body, runId, turnId: runId, seq, t: Date.now() });
43
+ };
44
+ // 4. Install the host + run inputs, bundle, and execute the program in-process.
45
+ const runsDir = join(projectDir, ".bw-runs", runId);
46
+ resetRuntime();
47
+ installHost(createDevHost({
48
+ manifest,
49
+ envVars,
50
+ envLabel: envPath,
51
+ artifactsDir: join(runsDir, "artifacts"),
52
+ emit,
53
+ }));
54
+ installInput(input);
55
+ installConfig({});
56
+ const staging = mkdtempSync(join(tmpdir(), "bw-dev-"));
57
+ const restoreSigint = (deps.onSigint ?? defaultOnSigint)(() => {
58
+ emit({ kind: "run_status", status: "cancelled" });
59
+ process.exit(130);
60
+ });
61
+ try {
62
+ const bundlePath = join(staging, "index.mjs");
63
+ writeFileSync(bundlePath, await bundleForDev(entry), "utf8");
64
+ emit({ kind: "run_status", status: "running" });
65
+ // A workflow program is a SCRIPT: importing the module IS running it (top-level body +
66
+ // top-level awaits). The import settles when the run completes; a top-level throw rejects it.
67
+ let mod;
68
+ try {
69
+ mod = (await import(pathToFileURL(bundlePath).href));
70
+ }
71
+ catch (err) {
72
+ // Output declared BEFORE the failure still counts — a failed watch/check often output()s
73
+ // its verdict and then throws to mark the run failed.
74
+ const declaredBeforeFailure = takeDeclaredOutput();
75
+ if (declaredBeforeFailure !== null) {
76
+ emit({ kind: "output", value: declaredBeforeFailure.value });
77
+ }
78
+ const message = err instanceof Error ? err.message : String(err);
79
+ emit({
80
+ kind: "run_status",
81
+ status: "failed",
82
+ error: { code: "PROGRAM_ERROR", message },
83
+ });
84
+ const hint = err instanceof CliError ? err.hint : undefined;
85
+ throw new CliError(`Run failed: ${message}`, hint, undefined, 1);
86
+ }
87
+ if (typeof mod.default === "function") {
88
+ console.error("warning: the program has a default export, which Boardwalk does not call — a workflow " +
89
+ "runs top-to-bottom as a script. Move the body to the top level (top-level await is fine).");
90
+ }
91
+ const declared = takeDeclaredOutput();
92
+ if (declared !== null)
93
+ emit({ kind: "output", value: declared.value });
94
+ emit({ kind: "run_status", status: "completed" });
95
+ }
96
+ finally {
97
+ restoreSigint();
98
+ resetRuntime();
99
+ rmSync(staging, { recursive: true, force: true });
100
+ }
101
+ }
102
+ /** Parse the env file into a map. A missing file is only an error when it was named explicitly. */
103
+ function loadEnvFile(path, explicit) {
104
+ let raw;
105
+ try {
106
+ raw = readFileSync(path, "utf8");
107
+ }
108
+ catch {
109
+ if (explicit) {
110
+ throw new CliError(`Env file not found: ${path}`);
111
+ }
112
+ return new Map();
113
+ }
114
+ const parsed = parseEnv(raw);
115
+ const out = new Map();
116
+ for (const [key, value] of Object.entries(parsed)) {
117
+ if (typeof value === "string")
118
+ out.set(key, value);
119
+ }
120
+ return out;
121
+ }
122
+ function defaultOnSigint(handler) {
123
+ process.once("SIGINT", handler);
124
+ return () => {
125
+ process.removeListener("SIGINT", handler);
126
+ };
127
+ }
128
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface InitOptions {
2
+ dir: string;
3
+ template: string;
4
+ }
5
+ export interface InitDeps {
6
+ log?: (line: string) => void;
7
+ fetchImpl?: typeof fetch;
8
+ env?: NodeJS.ProcessEnv;
9
+ }
10
+ export declare function runInit(opts: InitOptions, deps?: InitDeps): Promise<void>;
11
+ /** Derive a manifest-legal workflow name from the target directory's basename. */
12
+ export declare function workflowNameFor(absDir: string): string;