@w6w/sdk 0.3.0 → 0.4.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/dist/src/client.d.ts +28 -0
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +29 -0
- package/dist/src/client.js.map +1 -1
- package/dist/src/console/api-calls.d.ts +80 -0
- package/dist/src/console/api-calls.d.ts.map +1 -0
- package/dist/src/console/api-calls.js +69 -0
- package/dist/src/console/api-calls.js.map +1 -0
- package/dist/src/console/apps.d.ts +689 -0
- package/dist/src/console/apps.d.ts.map +1 -0
- package/dist/src/console/apps.js +402 -0
- package/dist/src/console/apps.js.map +1 -0
- package/dist/src/console/auth.d.ts +241 -0
- package/dist/src/console/auth.d.ts.map +1 -0
- package/dist/src/console/auth.js +173 -0
- package/dist/src/console/auth.js.map +1 -0
- package/dist/src/console/connections.d.ts +188 -0
- package/dist/src/console/connections.d.ts.map +1 -0
- package/dist/src/console/connections.js +182 -0
- package/dist/src/console/connections.js.map +1 -0
- package/dist/src/console/dashboard.d.ts +102 -0
- package/dist/src/console/dashboard.d.ts.map +1 -0
- package/dist/src/console/dashboard.js +59 -0
- package/dist/src/console/dashboard.js.map +1 -0
- package/dist/src/console/endpoints.d.ts +264 -0
- package/dist/src/console/endpoints.d.ts.map +1 -0
- package/dist/src/console/endpoints.js +164 -0
- package/dist/src/console/endpoints.js.map +1 -0
- package/dist/src/console/functions.d.ts +165 -0
- package/dist/src/console/functions.d.ts.map +1 -0
- package/dist/src/console/functions.js +117 -0
- package/dist/src/console/functions.js.map +1 -0
- package/dist/src/console/mod.d.ts +131 -0
- package/dist/src/console/mod.d.ts.map +1 -0
- package/dist/src/console/mod.js +121 -0
- package/dist/src/console/mod.js.map +1 -0
- package/dist/src/console/projects.d.ts +107 -0
- package/dist/src/console/projects.d.ts.map +1 -0
- package/dist/src/console/projects.js +97 -0
- package/dist/src/console/projects.js.map +1 -0
- package/dist/src/console/reliability.d.ts +149 -0
- package/dist/src/console/reliability.d.ts.map +1 -0
- package/dist/src/console/reliability.js +56 -0
- package/dist/src/console/reliability.js.map +1 -0
- package/dist/src/console/saved-tests.d.ts +198 -0
- package/dist/src/console/saved-tests.d.ts.map +1 -0
- package/dist/src/console/saved-tests.js +172 -0
- package/dist/src/console/saved-tests.js.map +1 -0
- package/dist/src/console/schedules.d.ts +127 -0
- package/dist/src/console/schedules.d.ts.map +1 -0
- package/dist/src/console/schedules.js +118 -0
- package/dist/src/console/schedules.js.map +1 -0
- package/dist/src/console/step-tests.d.ts +159 -0
- package/dist/src/console/step-tests.d.ts.map +1 -0
- package/dist/src/console/step-tests.js +129 -0
- package/dist/src/console/step-tests.js.map +1 -0
- package/dist/src/console/subscriptions.d.ts +199 -0
- package/dist/src/console/subscriptions.d.ts.map +1 -0
- package/dist/src/console/subscriptions.js +191 -0
- package/dist/src/console/subscriptions.js.map +1 -0
- package/dist/src/console/tenant-oauth-apps.d.ts +188 -0
- package/dist/src/console/tenant-oauth-apps.d.ts.map +1 -0
- package/dist/src/console/tenant-oauth-apps.js +152 -0
- package/dist/src/console/tenant-oauth-apps.js.map +1 -0
- package/dist/src/console/tokens.d.ts +159 -0
- package/dist/src/console/tokens.d.ts.map +1 -0
- package/dist/src/console/tokens.js +145 -0
- package/dist/src/console/tokens.js.map +1 -0
- package/dist/src/console/vault.d.ts +188 -0
- package/dist/src/console/vault.d.ts.map +1 -0
- package/dist/src/console/vault.js +164 -0
- package/dist/src/console/vault.js.map +1 -0
- package/dist/src/console/workflows.d.ts +243 -0
- package/dist/src/console/workflows.d.ts.map +1 -0
- package/dist/src/console/workflows.js +205 -0
- package/dist/src/console/workflows.js.map +1 -0
- package/dist/src/http.d.ts +32 -2
- package/dist/src/http.d.ts.map +1 -1
- package/dist/src/http.js +11 -2
- package/dist/src/http.js.map +1 -1
- package/dist/src/types.d.ts +2 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.console.vault.*` — the write-only secret store (list, get, create,
|
|
3
|
+
* update, delete, seal), relocated from the studio's own API client.
|
|
4
|
+
*
|
|
5
|
+
* **Studio-internal, not the published partner contract.** This namespace
|
|
6
|
+
* lives under the `console` subpath export (`@w6w/sdk/console`), excluded from
|
|
7
|
+
* `endpoints.json` and from the root barrel (`mod.ts`) — see `docs/console.md`
|
|
8
|
+
* and HITL-1 in this task's contract. `@w6w/sdk`'s instance-state mechanism
|
|
9
|
+
* pin still applies here exactly as it does to every other namespace
|
|
10
|
+
* (`docs/implementation.md` §MECHANISM PIN — instance state, never globals):
|
|
11
|
+
* this class holds no state of its own beyond the injected host, so two
|
|
12
|
+
* clients in one process never share a credential.
|
|
13
|
+
*
|
|
14
|
+
* **Write-only, no-plaintext-in-responses is the invariant this whole domain
|
|
15
|
+
* rests on** (`packages/server/packages/api/admin/vault.ts:1-21`'s own header
|
|
16
|
+
* comment: "plaintext values NEVER appear in a response"). `list`/`get` never
|
|
17
|
+
* carry `value` — by the server's wire contract itself, not by client
|
|
18
|
+
* discipline — which is why {@linkcode VaultSecretSummary} has no `value`
|
|
19
|
+
* field. `create`/`update` forward `value` verbatim to *write* it, and it is
|
|
20
|
+
* simply never echoed back. `seal` is the one deliberate exception, and even
|
|
21
|
+
* there it never returns the plaintext: it answers with a ciphertext envelope
|
|
22
|
+
* (`SecretValue`) — an encrypt-only oracle with no matching decrypt route, so
|
|
23
|
+
* an authed caller learns nothing they didn't already provide.
|
|
24
|
+
*
|
|
25
|
+
* Six methods relocate from the studio's own `// Vault` comment block
|
|
26
|
+
* (`packages/studio/src/api/client.ts:257-278` on the current merged tree) —
|
|
27
|
+
* field-for-field, not redesigned.
|
|
28
|
+
*
|
|
29
|
+
* `value` is opaque — forwarded verbatim on `create`/`update`/`seal`, never
|
|
30
|
+
* inspected, logged, or transformed. This is a security-adjacent discipline,
|
|
31
|
+
* not a style note: the whole point of this field is a caller-opaque secret
|
|
32
|
+
* payload.
|
|
33
|
+
*
|
|
34
|
+
* None of these methods take a `project` scoping parameter — vault secrets
|
|
35
|
+
* are subject-scoped like `vars`, not project-scoped — so `VaultHost` needs
|
|
36
|
+
* only the transport, mirroring `VarsHost`/`ConnectionsHost`, not
|
|
37
|
+
* `DocumentsHost`.
|
|
38
|
+
*
|
|
39
|
+
* @module
|
|
40
|
+
*/
|
|
41
|
+
import { path } from "../http.js";
|
|
42
|
+
import { unwrap } from "../types.js";
|
|
43
|
+
/**
|
|
44
|
+
* The `console.vault` namespace on a `W6wClient`.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const secrets = await client.console.vault.list();
|
|
49
|
+
* const created = await client.console.vault.create({ name: "openai_key", value: "sk-…" });
|
|
50
|
+
* await client.console.vault.update(created.id, { description: "Prod key" });
|
|
51
|
+
* const sealed = await client.console.vault.seal("sk-live-…");
|
|
52
|
+
* await client.console.vault.delete(created.id);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export class VaultApi {
|
|
56
|
+
#host;
|
|
57
|
+
/**
|
|
58
|
+
* @param host - The client this namespace issues requests through.
|
|
59
|
+
*/
|
|
60
|
+
constructor(host) {
|
|
61
|
+
this.#host = host;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* List the account's vault secrets.
|
|
65
|
+
*
|
|
66
|
+
* @returns The secrets, unwrapped from the `secrets` envelope. Never
|
|
67
|
+
* carries `value`.
|
|
68
|
+
*/
|
|
69
|
+
async list() {
|
|
70
|
+
const res = await this.#host.request({ method: "GET", path: "/vault" });
|
|
71
|
+
return unwrap(res, "secrets");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Fetch one secret's metadata.
|
|
75
|
+
*
|
|
76
|
+
* **Zero studio callers today** — built for SDK completeness only. No 404
|
|
77
|
+
* special-casing — propagates as `ApiError` like every other "get" in this
|
|
78
|
+
* package except `console.schedules.get`, which has its own documented,
|
|
79
|
+
* unrelated exception.
|
|
80
|
+
*
|
|
81
|
+
* @param id - The `sec_…` id.
|
|
82
|
+
* @returns The secret, unwrapped from the `secret` envelope. Never carries `value`.
|
|
83
|
+
* @throws {ApiError} `404 unknown_secret` when there is no such id.
|
|
84
|
+
*/
|
|
85
|
+
async get(id) {
|
|
86
|
+
const res = await this.#host.request({ method: "GET", path: path `/vault/${id}` });
|
|
87
|
+
return unwrap(res, "secret");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create a secret.
|
|
91
|
+
*
|
|
92
|
+
* `value` is opaque — forwarded verbatim, never inspected, logged, or
|
|
93
|
+
* transformed.
|
|
94
|
+
*
|
|
95
|
+
* @param body - `name` (unique, matches `^[a-z_][a-z0-9_]*$`), `value` (the
|
|
96
|
+
* plaintext to store), and an optional `description`.
|
|
97
|
+
* @returns The created secret, unwrapped from the `secret` envelope (the
|
|
98
|
+
* server answers `201`). Never carries `value`.
|
|
99
|
+
* @throws {ApiError} `400 invalid_name`/`invalid_value`/`invalid_description`; `409 secret_exists`.
|
|
100
|
+
*/
|
|
101
|
+
async create(body) {
|
|
102
|
+
const res = await this.#host.request({ method: "POST", path: "/vault", body });
|
|
103
|
+
return unwrap(res, "secret");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Update a secret: replace its value and/or its description.
|
|
107
|
+
*
|
|
108
|
+
* `value` is opaque — forwarded verbatim, never inspected, logged, or
|
|
109
|
+
* transformed, same discipline as {@linkcode create}.
|
|
110
|
+
*
|
|
111
|
+
* @param id - The `sec_…` id.
|
|
112
|
+
* @param body - `value` and/or `description`, forwarded verbatim.
|
|
113
|
+
* @returns The updated secret, unwrapped from the `secret` envelope. Never carries `value`.
|
|
114
|
+
* @throws {ApiError} `400 invalid_value`/`invalid_description`; `404 unknown_secret`.
|
|
115
|
+
*/
|
|
116
|
+
async update(id, body) {
|
|
117
|
+
const res = await this.#host.request({
|
|
118
|
+
method: "PATCH",
|
|
119
|
+
path: path `/vault/${id}`,
|
|
120
|
+
body,
|
|
121
|
+
});
|
|
122
|
+
return unwrap(res, "secret");
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Delete a secret.
|
|
126
|
+
*
|
|
127
|
+
* Returns nothing: the server's `{ok: true}` carries no information a
|
|
128
|
+
* caller can use, mirroring `console.projects.delete`/
|
|
129
|
+
* `console.schedules.delete`/`console.connections.delete` in this same
|
|
130
|
+
* package (NOT `console.apps.delete`, which is the one documented
|
|
131
|
+
* exception) — vault delete has no such value to preserve.
|
|
132
|
+
*
|
|
133
|
+
* @param id - The `sec_…` id.
|
|
134
|
+
* @throws {ApiError} `404 unknown_secret` when there is no such id.
|
|
135
|
+
*/
|
|
136
|
+
async delete(id) {
|
|
137
|
+
await this.#host.request({ method: "DELETE", path: path `/vault/${id}` });
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Encrypt an ad-hoc secret value into an at-rest ciphertext envelope,
|
|
141
|
+
* without storing it.
|
|
142
|
+
*
|
|
143
|
+
* **An encrypt-only oracle — there is no matching decrypt route.** The
|
|
144
|
+
* server's own header comment states the security property directly: "an
|
|
145
|
+
* authed caller learns nothing they didn't provide." `value` is opaque —
|
|
146
|
+
* forwarded verbatim, never inspected, logged, or transformed. **No
|
|
147
|
+
* envelope key to peel on the request side** — the body IS `{ value }` —
|
|
148
|
+
* but the *response* IS enveloped under `sealed`, unlike `console.
|
|
149
|
+
* connections.test`'s/`console.reliability.list`'s whole-body responses.
|
|
150
|
+
*
|
|
151
|
+
* @param value - The plaintext to seal. Never logged, never echoed back.
|
|
152
|
+
* @returns The ciphertext envelope, unwrapped from the `sealed` envelope.
|
|
153
|
+
* @throws {ApiError} `400 invalid_value` when `value` is empty.
|
|
154
|
+
*/
|
|
155
|
+
async seal(value) {
|
|
156
|
+
const res = await this.#host.request({
|
|
157
|
+
method: "POST",
|
|
158
|
+
path: "/vault/seal",
|
|
159
|
+
body: { value },
|
|
160
|
+
});
|
|
161
|
+
return unwrap(res, "sealed");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../../../src/console/vault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAqB,IAAI,EAAuB,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAkDrC;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,QAAQ;IACV,KAAK,CAAY;IAE1B;;OAEG;IACH,YAAY,IAAe;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjF,OAAO,MAAM,CAAuB,GAAG,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAA,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3F,OAAO,MAAM,CAAqB,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,CACV,IAA2D;QAE3D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACxF,OAAO,MAAM,CAAqB,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,MAAM,CACV,EAAU,EACV,IAA8C;QAE9C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI,CAAA,UAAU,EAAE,EAAE;YACxB,IAAI;SACL,CAAC,CAAC;QACH,OAAO,MAAM,CAAqB,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAA,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,EAAE,KAAK,EAAE;SAChB,CAAC,CAAC;QACH,OAAO,MAAM,CAAc,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.console.workflows.*` — the workflow definition/lifecycle and run
|
|
3
|
+
* surface (`get`, `upsert`, `archive`, `delete`, `listRuns`, `getRun`),
|
|
4
|
+
* relocated from the studio's own API client.
|
|
5
|
+
*
|
|
6
|
+
* **Studio-internal, not the published partner contract.** This namespace
|
|
7
|
+
* lives under the `console` subpath export (`@w6w/sdk/console`), excluded from
|
|
8
|
+
* `endpoints.json` and from the root barrel (`mod.ts`) — see `docs/console.md`
|
|
9
|
+
* and HITL-1 in this task's contract. `@w6w/sdk`'s instance-state mechanism
|
|
10
|
+
* pin still applies here exactly as it does to every other namespace
|
|
11
|
+
* (`docs/implementation.md` §MECHANISM PIN — instance state, never globals):
|
|
12
|
+
* this class holds no state of its own beyond the injected host, so two
|
|
13
|
+
* clients in one process never share a credential.
|
|
14
|
+
*
|
|
15
|
+
* **Console placement is the same precedent as `console.connections`'s
|
|
16
|
+
* `HITL-10`, not a fresh judgment call — see `HITL.md` and `plan.md`'s SP2.3
|
|
17
|
+
* section for the full investigation.** `endpoints.json`'s `outOfScope` array
|
|
18
|
+
* names "all write operations on connections and workflows" together, with the
|
|
19
|
+
* identical "in this version" framing HITL-10 already resolved for
|
|
20
|
+
* connections. The server routes here (`admin/workflows.ts`) are, like
|
|
21
|
+
* connections, plain stateless handlers over an already-resolved request
|
|
22
|
+
* body/precondition header — no interactive flow the SDK method itself would
|
|
23
|
+
* need to conduct. Console placement is safe for studio's own use; it does not
|
|
24
|
+
* by itself justify promotion to the partner surface (cli/python lockstep; no
|
|
25
|
+
* documented partner story exists yet either) — that promotion, if it ever
|
|
26
|
+
* happens, is a dedicated future project.
|
|
27
|
+
*
|
|
28
|
+
* **`list` and `run` are NOT part of this domain.** Both already exist on the
|
|
29
|
+
* BASE namespace (`client.workflows.list()`/`client.workflows.run()`,
|
|
30
|
+
* `../workflows.ts`) and studio reuses them verbatim — adding a duplicate
|
|
31
|
+
* `list`/`run` under `console.workflows` would give a caller two ways to reach
|
|
32
|
+
* the same route, exactly the anti-duplication defect this project's own
|
|
33
|
+
* rules flag. **No poll loop lives here either**: `../workflows.ts`'s own
|
|
34
|
+
* module doc pins "no client-side polling" for the whole package, and
|
|
35
|
+
* `getRun` below is deliberately a single request with no retry — the caller
|
|
36
|
+
* (studio's `lib/workflow-poll.ts`) owns the loop.
|
|
37
|
+
*
|
|
38
|
+
* Five of six methods relocate from the studio's `// Workflows` comment block
|
|
39
|
+
* (`packages/studio/src/api/client.ts:254-331`): `getWorkflow`→`get`,
|
|
40
|
+
* `createWorkflow`→`upsert`, `archiveWorkflow`→`archive`,
|
|
41
|
+
* `deleteWorkflow`→`delete`, `listRuns`→`listRuns`. `getRun` is genuinely NEW
|
|
42
|
+
* here — `client.ts`'s own `getRun` method is dead code today (zero callers),
|
|
43
|
+
* but this task gives it a real consumer: `runWorkflow`'s poll loop, ported
|
|
44
|
+
* into studio's `lib/workflow-poll.ts`, calls it.
|
|
45
|
+
*
|
|
46
|
+
* None of the six methods take a client-side default-project fallback — they
|
|
47
|
+
* are addressed by `wf_…`/`run_…` id (plus an optional explicit `?project=`
|
|
48
|
+
* on `upsert`), so `WorkflowsHost` needs only the transport, mirroring
|
|
49
|
+
* `SchedulesHost`/`ProjectsHost`, not the BASE `WorkflowsHost` (`../workflows.ts`),
|
|
50
|
+
* which additionally reads `config.project` as `list()`'s default.
|
|
51
|
+
*
|
|
52
|
+
* @module
|
|
53
|
+
*/
|
|
54
|
+
import { type HttpResponse, type RequestOptions } from "../http.ts";
|
|
55
|
+
import { type RunStatus, type StepError } from "../types.ts";
|
|
56
|
+
/**
|
|
57
|
+
* The slice of `W6wClient` this namespace needs: the transport, and nothing
|
|
58
|
+
* else. Structural rather than a concrete client type, so the namespace stays
|
|
59
|
+
* independently constructible in a test and this module never imports the
|
|
60
|
+
* client back — mirrors `SchedulesHost` in `./schedules.ts`.
|
|
61
|
+
*/
|
|
62
|
+
export interface WorkflowsHost {
|
|
63
|
+
/** Perform one request. */
|
|
64
|
+
request<T>(options: RequestOptions): Promise<HttpResponse<T>>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A workflow run's full state, as `GET /runs/:id` returns it.
|
|
68
|
+
*
|
|
69
|
+
* Field-for-field, relocated from `packages/studio/src/api/types.ts:84-102`,
|
|
70
|
+
* with ONE deliberate deviation from studio's local shape: `error` and `steps`
|
|
71
|
+
* stay OPAQUE (`unknown`/`Record<string, unknown>`), matching this package's
|
|
72
|
+
* own documented philosophy for `RunResult` (`../types.ts` — "a client that
|
|
73
|
+
* modelled their internals would be wrong for someone"). Studio's local type
|
|
74
|
+
* typed `error` as a structured `{code,message,…}` and `steps` as
|
|
75
|
+
* `Record<string, StepExecution>`; that richer typing does not carry over
|
|
76
|
+
* here, on purpose, for consistency with every other run-shaped type in this
|
|
77
|
+
* package.
|
|
78
|
+
*
|
|
79
|
+
* Defined LOCALLY in this file, not in the shared `../types.ts`: it is
|
|
80
|
+
* consumed only by console methods, never by base `run()`/`list()`, mirroring
|
|
81
|
+
* where `Schedule`/`Project` live (inside their own `console/*.ts` files).
|
|
82
|
+
*/
|
|
83
|
+
export interface RunState {
|
|
84
|
+
/** Server-issued run handle, `run_…`. */
|
|
85
|
+
runId: string;
|
|
86
|
+
/** The workflow this run belongs to. */
|
|
87
|
+
workflowId: string;
|
|
88
|
+
/** Where the run has got to. */
|
|
89
|
+
status: RunStatus;
|
|
90
|
+
/** Variables the run was started with. Opaque pass-through. */
|
|
91
|
+
variables: Record<string, unknown>;
|
|
92
|
+
/** Per-step state, keyed by step id. Opaque pass-through. */
|
|
93
|
+
steps: Record<string, unknown>;
|
|
94
|
+
/** The run's output when it finished; absent while it is still going. */
|
|
95
|
+
output?: unknown;
|
|
96
|
+
/** The run-level error when it failed; absent otherwise. Data, never a raised exception. Opaque pass-through. */
|
|
97
|
+
error?: unknown;
|
|
98
|
+
/** Per-step failures, when the server reports them. */
|
|
99
|
+
stepErrors?: StepError[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* One row of `listRuns`'s result — a run's summary, not its full state.
|
|
103
|
+
*
|
|
104
|
+
* Field-for-field, relocated from `packages/studio/src/api/types.ts:84-102`
|
|
105
|
+
* (the summary subset). Defined LOCALLY, same reasoning as {@linkcode RunState}.
|
|
106
|
+
*/
|
|
107
|
+
export interface RunSummary {
|
|
108
|
+
/** Server-issued run handle, `run_…`. */
|
|
109
|
+
runId: string;
|
|
110
|
+
/** Where the run has got to. */
|
|
111
|
+
status: RunStatus;
|
|
112
|
+
/** What triggered this run, e.g. `"manual"`, `"schedule"`, `"webhook"`. */
|
|
113
|
+
trigger: string;
|
|
114
|
+
/** ISO-8601 timestamp. */
|
|
115
|
+
startedAt: string;
|
|
116
|
+
/** ISO-8601 timestamp, or `null` while the run is still going. */
|
|
117
|
+
finishedAt: string | null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The `console.workflows` namespace on a `W6wClient`.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* const { workflow, updatedAt } = await client.console.workflows.get("wf_1");
|
|
125
|
+
* const saved = await client.console.workflows.upsert(workflow, { ifUnmodifiedSince: updatedAt });
|
|
126
|
+
* const runs = await client.console.workflows.listRuns("wf_1");
|
|
127
|
+
* const run = await client.console.workflows.getRun(runs[0].runId);
|
|
128
|
+
* await client.console.workflows.archive("wf_1");
|
|
129
|
+
* await client.console.workflows.delete("wf_1");
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare class WorkflowsApi {
|
|
133
|
+
#private;
|
|
134
|
+
/**
|
|
135
|
+
* @param host - The client this namespace issues requests through.
|
|
136
|
+
*/
|
|
137
|
+
constructor(host: WorkflowsHost);
|
|
138
|
+
/**
|
|
139
|
+
* Fetch one workflow's stored definition.
|
|
140
|
+
*
|
|
141
|
+
* `workflow` is the merged definition (the stored definition overlaid with
|
|
142
|
+
* `status` and `tags`) — an arbitrary JSON object, never a fixed shape, kept
|
|
143
|
+
* as `Record<string, unknown>` exactly as `client.ts` typed it. `updatedAt`
|
|
144
|
+
* is TOP-LEVEL, never inside `workflow` — it is the optimistic-concurrency
|
|
145
|
+
* token a save echoes back via {@linkcode upsert}'s `ifUnmodifiedSince`.
|
|
146
|
+
*
|
|
147
|
+
* No 404 special-casing — propagates as `ApiError` like every other "get" in
|
|
148
|
+
* this package except `console.schedules.get`'s documented, unrelated
|
|
149
|
+
* exception.
|
|
150
|
+
*
|
|
151
|
+
* @param id - The `wf_…` id.
|
|
152
|
+
* @returns The whole response body — no envelope key to peel.
|
|
153
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
154
|
+
*/
|
|
155
|
+
get(id: string): Promise<{
|
|
156
|
+
workflow: Record<string, unknown>;
|
|
157
|
+
sourceRef: string | null;
|
|
158
|
+
updatedAt: string;
|
|
159
|
+
}>;
|
|
160
|
+
/**
|
|
161
|
+
* Register (create or overwrite) a workflow definition.
|
|
162
|
+
*
|
|
163
|
+
* `definition` is the whole definition, sent verbatim as the request body —
|
|
164
|
+
* not wrapped in an envelope key. `options.ifUnmodifiedSince` is the
|
|
165
|
+
* optional optimistic-concurrency precondition: pass the exact `updatedAt`
|
|
166
|
+
* this client last saw (from {@linkcode get}, or a prior `upsert`'s own
|
|
167
|
+
* `updatedAt`) and the server rejects the write with `409 workflow_stale` if
|
|
168
|
+
* the stored row has moved on since. Omitted, the save is last-write-wins
|
|
169
|
+
* and the header is never sent at all — never as an empty or `"null"`
|
|
170
|
+
* string, mirroring the server's own conditional exactly
|
|
171
|
+
* (`admin/workflows.ts`).
|
|
172
|
+
*
|
|
173
|
+
* @param definition - The whole workflow definition, forwarded verbatim.
|
|
174
|
+
* @param options - `project` scopes the write; `ifUnmodifiedSince` is the concurrency precondition.
|
|
175
|
+
* @returns The new/updated workflow's id and name, whether a schedule was (re)applied, and the new `updatedAt`.
|
|
176
|
+
* @throws {ApiError} `400 invalid_workflow`/`invalid_body`/`invalid_precondition`.
|
|
177
|
+
* @throws {ApiError} `409 workflow_conflict` — another `(tenant,subject)` owns this id. NOT recoverable by reloading.
|
|
178
|
+
* @throws {ApiError} `409 workflow_stale` — the precondition didn't match the stored `updatedAt`. IS recoverable by reloading and re-saving.
|
|
179
|
+
*/
|
|
180
|
+
upsert(definition: unknown, options?: {
|
|
181
|
+
project?: string;
|
|
182
|
+
ifUnmodifiedSince?: string | null;
|
|
183
|
+
}): Promise<{
|
|
184
|
+
workflow: {
|
|
185
|
+
id: string;
|
|
186
|
+
name: string;
|
|
187
|
+
};
|
|
188
|
+
scheduled: boolean;
|
|
189
|
+
updatedAt: string;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* Archive a workflow. One-way — no unarchive route exists anywhere on this
|
|
193
|
+
* domain.
|
|
194
|
+
*
|
|
195
|
+
* Idempotent: archiving an already-archived workflow re-returns it
|
|
196
|
+
* unchanged rather than erroring.
|
|
197
|
+
*
|
|
198
|
+
* @param id - The `wf_…` id.
|
|
199
|
+
* @returns The archived workflow — no envelope key to peel.
|
|
200
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
201
|
+
*/
|
|
202
|
+
archive(id: string): Promise<{
|
|
203
|
+
workflow: Record<string, unknown>;
|
|
204
|
+
}>;
|
|
205
|
+
/**
|
|
206
|
+
* Delete a workflow. Cascade-deletes its runs/schedules/subscriptions
|
|
207
|
+
* server-side; nothing for the caller to do about that.
|
|
208
|
+
*
|
|
209
|
+
* The server requires archive-then-delete — deleting a workflow whose status
|
|
210
|
+
* isn't `"archived"` yet answers `409 workflow_not_archived`, which this
|
|
211
|
+
* method does NOT catch. That is a real signal the caller must handle;
|
|
212
|
+
* enforcing archive-then-delete is not this method's job.
|
|
213
|
+
*
|
|
214
|
+
* Returns nothing: the server's `{ok: true}` carries no information a
|
|
215
|
+
* caller can use.
|
|
216
|
+
*
|
|
217
|
+
* @param id - The `wf_…` id.
|
|
218
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
219
|
+
* @throws {ApiError} `409 workflow_not_archived` when the workflow exists but is not archived yet.
|
|
220
|
+
*/
|
|
221
|
+
delete(id: string): Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* List a workflow's runs.
|
|
224
|
+
*
|
|
225
|
+
* @param id - The `wf_…` id.
|
|
226
|
+
* @returns The runs, unwrapped from the `runs` envelope.
|
|
227
|
+
* @throws {ApiError} `404 unknown_workflow` — an ownership gate: the workflow must belong to the caller.
|
|
228
|
+
*/
|
|
229
|
+
listRuns(id: string): Promise<RunSummary[]>;
|
|
230
|
+
/**
|
|
231
|
+
* Fetch one run's full state.
|
|
232
|
+
*
|
|
233
|
+
* **One request, one answer — no polling, no `wait`, no retry.** The caller
|
|
234
|
+
* (studio's `lib/workflow-poll.ts`) owns the loop; see this module's header
|
|
235
|
+
* and `../workflows.ts`'s own "no client-side polling" pin.
|
|
236
|
+
*
|
|
237
|
+
* @param runId - The `run_…` id.
|
|
238
|
+
* @returns The run, unwrapped from the `run` envelope.
|
|
239
|
+
* @throws {ApiError} `404 unknown_run` — covers both "no such run" and "not your workflow"; the caller cannot and does not need to distinguish them.
|
|
240
|
+
*/
|
|
241
|
+
getRun(runId: string): Promise<RunState>;
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=workflows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../src/console/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAQ,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAU,MAAM,aAAa,CAAC;AAKrE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,QAAQ;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,MAAM,EAAE,SAAS,CAAC;IAClB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,MAAM,EAAE,SAAS,CAAC;IAClB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAY;;IAGvB;;OAEG;gBACS,IAAI,EAAE,aAAa;IAI/B;;;;;;;;;;;;;;;;OAgBG;IACG,GAAG,CACP,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAU9F;;;;;;;;;;;;;;;;;;;OAmBG;IACG,MAAM,CACV,UAAU,EAAE,OAAO,EACnB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAChE,OAAO,CAAC;QAAE,QAAQ,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAe7F;;;;;;;;;;OAUG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IAQzE;;;;;;;;;;;;;;;OAeG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;OAMG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQjD;;;;;;;;;;OAUG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAO/C"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.console.workflows.*` — the workflow definition/lifecycle and run
|
|
3
|
+
* surface (`get`, `upsert`, `archive`, `delete`, `listRuns`, `getRun`),
|
|
4
|
+
* relocated from the studio's own API client.
|
|
5
|
+
*
|
|
6
|
+
* **Studio-internal, not the published partner contract.** This namespace
|
|
7
|
+
* lives under the `console` subpath export (`@w6w/sdk/console`), excluded from
|
|
8
|
+
* `endpoints.json` and from the root barrel (`mod.ts`) — see `docs/console.md`
|
|
9
|
+
* and HITL-1 in this task's contract. `@w6w/sdk`'s instance-state mechanism
|
|
10
|
+
* pin still applies here exactly as it does to every other namespace
|
|
11
|
+
* (`docs/implementation.md` §MECHANISM PIN — instance state, never globals):
|
|
12
|
+
* this class holds no state of its own beyond the injected host, so two
|
|
13
|
+
* clients in one process never share a credential.
|
|
14
|
+
*
|
|
15
|
+
* **Console placement is the same precedent as `console.connections`'s
|
|
16
|
+
* `HITL-10`, not a fresh judgment call — see `HITL.md` and `plan.md`'s SP2.3
|
|
17
|
+
* section for the full investigation.** `endpoints.json`'s `outOfScope` array
|
|
18
|
+
* names "all write operations on connections and workflows" together, with the
|
|
19
|
+
* identical "in this version" framing HITL-10 already resolved for
|
|
20
|
+
* connections. The server routes here (`admin/workflows.ts`) are, like
|
|
21
|
+
* connections, plain stateless handlers over an already-resolved request
|
|
22
|
+
* body/precondition header — no interactive flow the SDK method itself would
|
|
23
|
+
* need to conduct. Console placement is safe for studio's own use; it does not
|
|
24
|
+
* by itself justify promotion to the partner surface (cli/python lockstep; no
|
|
25
|
+
* documented partner story exists yet either) — that promotion, if it ever
|
|
26
|
+
* happens, is a dedicated future project.
|
|
27
|
+
*
|
|
28
|
+
* **`list` and `run` are NOT part of this domain.** Both already exist on the
|
|
29
|
+
* BASE namespace (`client.workflows.list()`/`client.workflows.run()`,
|
|
30
|
+
* `../workflows.ts`) and studio reuses them verbatim — adding a duplicate
|
|
31
|
+
* `list`/`run` under `console.workflows` would give a caller two ways to reach
|
|
32
|
+
* the same route, exactly the anti-duplication defect this project's own
|
|
33
|
+
* rules flag. **No poll loop lives here either**: `../workflows.ts`'s own
|
|
34
|
+
* module doc pins "no client-side polling" for the whole package, and
|
|
35
|
+
* `getRun` below is deliberately a single request with no retry — the caller
|
|
36
|
+
* (studio's `lib/workflow-poll.ts`) owns the loop.
|
|
37
|
+
*
|
|
38
|
+
* Five of six methods relocate from the studio's `// Workflows` comment block
|
|
39
|
+
* (`packages/studio/src/api/client.ts:254-331`): `getWorkflow`→`get`,
|
|
40
|
+
* `createWorkflow`→`upsert`, `archiveWorkflow`→`archive`,
|
|
41
|
+
* `deleteWorkflow`→`delete`, `listRuns`→`listRuns`. `getRun` is genuinely NEW
|
|
42
|
+
* here — `client.ts`'s own `getRun` method is dead code today (zero callers),
|
|
43
|
+
* but this task gives it a real consumer: `runWorkflow`'s poll loop, ported
|
|
44
|
+
* into studio's `lib/workflow-poll.ts`, calls it.
|
|
45
|
+
*
|
|
46
|
+
* None of the six methods take a client-side default-project fallback — they
|
|
47
|
+
* are addressed by `wf_…`/`run_…` id (plus an optional explicit `?project=`
|
|
48
|
+
* on `upsert`), so `WorkflowsHost` needs only the transport, mirroring
|
|
49
|
+
* `SchedulesHost`/`ProjectsHost`, not the BASE `WorkflowsHost` (`../workflows.ts`),
|
|
50
|
+
* which additionally reads `config.project` as `list()`'s default.
|
|
51
|
+
*
|
|
52
|
+
* @module
|
|
53
|
+
*/
|
|
54
|
+
import { path } from "../http.js";
|
|
55
|
+
import { unwrap } from "../types.js";
|
|
56
|
+
/** The precondition header `upsert` sends when `ifUnmodifiedSince` is given. */
|
|
57
|
+
const PRECONDITION_HEADER = "x-w6w-if-unmodified-since";
|
|
58
|
+
/**
|
|
59
|
+
* The `console.workflows` namespace on a `W6wClient`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const { workflow, updatedAt } = await client.console.workflows.get("wf_1");
|
|
64
|
+
* const saved = await client.console.workflows.upsert(workflow, { ifUnmodifiedSince: updatedAt });
|
|
65
|
+
* const runs = await client.console.workflows.listRuns("wf_1");
|
|
66
|
+
* const run = await client.console.workflows.getRun(runs[0].runId);
|
|
67
|
+
* await client.console.workflows.archive("wf_1");
|
|
68
|
+
* await client.console.workflows.delete("wf_1");
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export class WorkflowsApi {
|
|
72
|
+
#host;
|
|
73
|
+
/**
|
|
74
|
+
* @param host - The client this namespace issues requests through.
|
|
75
|
+
*/
|
|
76
|
+
constructor(host) {
|
|
77
|
+
this.#host = host;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fetch one workflow's stored definition.
|
|
81
|
+
*
|
|
82
|
+
* `workflow` is the merged definition (the stored definition overlaid with
|
|
83
|
+
* `status` and `tags`) — an arbitrary JSON object, never a fixed shape, kept
|
|
84
|
+
* as `Record<string, unknown>` exactly as `client.ts` typed it. `updatedAt`
|
|
85
|
+
* is TOP-LEVEL, never inside `workflow` — it is the optimistic-concurrency
|
|
86
|
+
* token a save echoes back via {@linkcode upsert}'s `ifUnmodifiedSince`.
|
|
87
|
+
*
|
|
88
|
+
* No 404 special-casing — propagates as `ApiError` like every other "get" in
|
|
89
|
+
* this package except `console.schedules.get`'s documented, unrelated
|
|
90
|
+
* exception.
|
|
91
|
+
*
|
|
92
|
+
* @param id - The `wf_…` id.
|
|
93
|
+
* @returns The whole response body — no envelope key to peel.
|
|
94
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
95
|
+
*/
|
|
96
|
+
async get(id) {
|
|
97
|
+
const res = await this.#host.request({
|
|
98
|
+
method: "GET",
|
|
99
|
+
path: path `/workflows/${id}`,
|
|
100
|
+
});
|
|
101
|
+
return res.body;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Register (create or overwrite) a workflow definition.
|
|
105
|
+
*
|
|
106
|
+
* `definition` is the whole definition, sent verbatim as the request body —
|
|
107
|
+
* not wrapped in an envelope key. `options.ifUnmodifiedSince` is the
|
|
108
|
+
* optional optimistic-concurrency precondition: pass the exact `updatedAt`
|
|
109
|
+
* this client last saw (from {@linkcode get}, or a prior `upsert`'s own
|
|
110
|
+
* `updatedAt`) and the server rejects the write with `409 workflow_stale` if
|
|
111
|
+
* the stored row has moved on since. Omitted, the save is last-write-wins
|
|
112
|
+
* and the header is never sent at all — never as an empty or `"null"`
|
|
113
|
+
* string, mirroring the server's own conditional exactly
|
|
114
|
+
* (`admin/workflows.ts`).
|
|
115
|
+
*
|
|
116
|
+
* @param definition - The whole workflow definition, forwarded verbatim.
|
|
117
|
+
* @param options - `project` scopes the write; `ifUnmodifiedSince` is the concurrency precondition.
|
|
118
|
+
* @returns The new/updated workflow's id and name, whether a schedule was (re)applied, and the new `updatedAt`.
|
|
119
|
+
* @throws {ApiError} `400 invalid_workflow`/`invalid_body`/`invalid_precondition`.
|
|
120
|
+
* @throws {ApiError} `409 workflow_conflict` — another `(tenant,subject)` owns this id. NOT recoverable by reloading.
|
|
121
|
+
* @throws {ApiError} `409 workflow_stale` — the precondition didn't match the stored `updatedAt`. IS recoverable by reloading and re-saving.
|
|
122
|
+
*/
|
|
123
|
+
async upsert(definition, options) {
|
|
124
|
+
const res = await this.#host.request({
|
|
125
|
+
method: "POST",
|
|
126
|
+
path: "/workflows",
|
|
127
|
+
query: { project: options?.project },
|
|
128
|
+
body: definition,
|
|
129
|
+
...(options?.ifUnmodifiedSince
|
|
130
|
+
? { headers: { [PRECONDITION_HEADER]: options.ifUnmodifiedSince } }
|
|
131
|
+
: {}),
|
|
132
|
+
});
|
|
133
|
+
return res.body;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Archive a workflow. One-way — no unarchive route exists anywhere on this
|
|
137
|
+
* domain.
|
|
138
|
+
*
|
|
139
|
+
* Idempotent: archiving an already-archived workflow re-returns it
|
|
140
|
+
* unchanged rather than erroring.
|
|
141
|
+
*
|
|
142
|
+
* @param id - The `wf_…` id.
|
|
143
|
+
* @returns The archived workflow — no envelope key to peel.
|
|
144
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
145
|
+
*/
|
|
146
|
+
async archive(id) {
|
|
147
|
+
const res = await this.#host.request({
|
|
148
|
+
method: "POST",
|
|
149
|
+
path: path `/workflows/${id}/archive`,
|
|
150
|
+
});
|
|
151
|
+
return res.body;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Delete a workflow. Cascade-deletes its runs/schedules/subscriptions
|
|
155
|
+
* server-side; nothing for the caller to do about that.
|
|
156
|
+
*
|
|
157
|
+
* The server requires archive-then-delete — deleting a workflow whose status
|
|
158
|
+
* isn't `"archived"` yet answers `409 workflow_not_archived`, which this
|
|
159
|
+
* method does NOT catch. That is a real signal the caller must handle;
|
|
160
|
+
* enforcing archive-then-delete is not this method's job.
|
|
161
|
+
*
|
|
162
|
+
* Returns nothing: the server's `{ok: true}` carries no information a
|
|
163
|
+
* caller can use.
|
|
164
|
+
*
|
|
165
|
+
* @param id - The `wf_…` id.
|
|
166
|
+
* @throws {ApiError} `404 unknown_workflow` when there is no such id.
|
|
167
|
+
* @throws {ApiError} `409 workflow_not_archived` when the workflow exists but is not archived yet.
|
|
168
|
+
*/
|
|
169
|
+
async delete(id) {
|
|
170
|
+
await this.#host.request({ method: "DELETE", path: path `/workflows/${id}` });
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* List a workflow's runs.
|
|
174
|
+
*
|
|
175
|
+
* @param id - The `wf_…` id.
|
|
176
|
+
* @returns The runs, unwrapped from the `runs` envelope.
|
|
177
|
+
* @throws {ApiError} `404 unknown_workflow` — an ownership gate: the workflow must belong to the caller.
|
|
178
|
+
*/
|
|
179
|
+
async listRuns(id) {
|
|
180
|
+
const res = await this.#host.request({
|
|
181
|
+
method: "GET",
|
|
182
|
+
path: path `/workflows/${id}/runs`,
|
|
183
|
+
});
|
|
184
|
+
return unwrap(res, "runs");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Fetch one run's full state.
|
|
188
|
+
*
|
|
189
|
+
* **One request, one answer — no polling, no `wait`, no retry.** The caller
|
|
190
|
+
* (studio's `lib/workflow-poll.ts`) owns the loop; see this module's header
|
|
191
|
+
* and `../workflows.ts`'s own "no client-side polling" pin.
|
|
192
|
+
*
|
|
193
|
+
* @param runId - The `run_…` id.
|
|
194
|
+
* @returns The run, unwrapped from the `run` envelope.
|
|
195
|
+
* @throws {ApiError} `404 unknown_run` — covers both "no such run" and "not your workflow"; the caller cannot and does not need to distinguish them.
|
|
196
|
+
*/
|
|
197
|
+
async getRun(runId) {
|
|
198
|
+
const res = await this.#host.request({
|
|
199
|
+
method: "GET",
|
|
200
|
+
path: path `/runs/${runId}`,
|
|
201
|
+
});
|
|
202
|
+
return unwrap(res, "run");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=workflows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/console/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAAqB,IAAI,EAAuB,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAkC,MAAM,EAAE,MAAM,aAAa,CAAC;AAErE,gFAAgF;AAChF,MAAM,mBAAmB,GAAG,2BAA2B,CAAC;AAoExD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,YAAY;IACd,KAAK,CAAgB;IAE9B;;OAEG;IACH,YAAY,IAAmB;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,GAAG,CACP,EAAU;QAEV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAElC;YACA,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAA,cAAc,EAAE,EAAE;SAC7B,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,CAAC,MAAM,CACV,UAAmB,EACnB,OAAiE;QAEjE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAElC;YACA,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YACpC,IAAI,EAAE,UAAU;YAChB,GAAG,CAAC,OAAO,EAAE,iBAAiB;gBAC5B,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,EAAE;gBACnE,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAwC;YAC1E,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAA,cAAc,EAAE,UAAU;SACrC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAA,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;IACxF,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAA,cAAc,EAAE,OAAO;SAClC,CAAC,CAAC;QACH,OAAO,MAAM,CAAe,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa;QACxB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAA,SAAS,KAAK,EAAE;SAC3B,CAAC,CAAC;QACH,OAAO,MAAM,CAAW,GAAG,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;CACF"}
|