@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.
Files changed (84) hide show
  1. package/dist/src/client.d.ts +28 -0
  2. package/dist/src/client.d.ts.map +1 -1
  3. package/dist/src/client.js +29 -0
  4. package/dist/src/client.js.map +1 -1
  5. package/dist/src/console/api-calls.d.ts +80 -0
  6. package/dist/src/console/api-calls.d.ts.map +1 -0
  7. package/dist/src/console/api-calls.js +69 -0
  8. package/dist/src/console/api-calls.js.map +1 -0
  9. package/dist/src/console/apps.d.ts +689 -0
  10. package/dist/src/console/apps.d.ts.map +1 -0
  11. package/dist/src/console/apps.js +402 -0
  12. package/dist/src/console/apps.js.map +1 -0
  13. package/dist/src/console/auth.d.ts +241 -0
  14. package/dist/src/console/auth.d.ts.map +1 -0
  15. package/dist/src/console/auth.js +173 -0
  16. package/dist/src/console/auth.js.map +1 -0
  17. package/dist/src/console/connections.d.ts +188 -0
  18. package/dist/src/console/connections.d.ts.map +1 -0
  19. package/dist/src/console/connections.js +182 -0
  20. package/dist/src/console/connections.js.map +1 -0
  21. package/dist/src/console/dashboard.d.ts +102 -0
  22. package/dist/src/console/dashboard.d.ts.map +1 -0
  23. package/dist/src/console/dashboard.js +59 -0
  24. package/dist/src/console/dashboard.js.map +1 -0
  25. package/dist/src/console/endpoints.d.ts +264 -0
  26. package/dist/src/console/endpoints.d.ts.map +1 -0
  27. package/dist/src/console/endpoints.js +164 -0
  28. package/dist/src/console/endpoints.js.map +1 -0
  29. package/dist/src/console/functions.d.ts +165 -0
  30. package/dist/src/console/functions.d.ts.map +1 -0
  31. package/dist/src/console/functions.js +117 -0
  32. package/dist/src/console/functions.js.map +1 -0
  33. package/dist/src/console/mod.d.ts +131 -0
  34. package/dist/src/console/mod.d.ts.map +1 -0
  35. package/dist/src/console/mod.js +121 -0
  36. package/dist/src/console/mod.js.map +1 -0
  37. package/dist/src/console/projects.d.ts +107 -0
  38. package/dist/src/console/projects.d.ts.map +1 -0
  39. package/dist/src/console/projects.js +97 -0
  40. package/dist/src/console/projects.js.map +1 -0
  41. package/dist/src/console/reliability.d.ts +149 -0
  42. package/dist/src/console/reliability.d.ts.map +1 -0
  43. package/dist/src/console/reliability.js +56 -0
  44. package/dist/src/console/reliability.js.map +1 -0
  45. package/dist/src/console/saved-tests.d.ts +198 -0
  46. package/dist/src/console/saved-tests.d.ts.map +1 -0
  47. package/dist/src/console/saved-tests.js +172 -0
  48. package/dist/src/console/saved-tests.js.map +1 -0
  49. package/dist/src/console/schedules.d.ts +127 -0
  50. package/dist/src/console/schedules.d.ts.map +1 -0
  51. package/dist/src/console/schedules.js +118 -0
  52. package/dist/src/console/schedules.js.map +1 -0
  53. package/dist/src/console/step-tests.d.ts +159 -0
  54. package/dist/src/console/step-tests.d.ts.map +1 -0
  55. package/dist/src/console/step-tests.js +129 -0
  56. package/dist/src/console/step-tests.js.map +1 -0
  57. package/dist/src/console/subscriptions.d.ts +199 -0
  58. package/dist/src/console/subscriptions.d.ts.map +1 -0
  59. package/dist/src/console/subscriptions.js +191 -0
  60. package/dist/src/console/subscriptions.js.map +1 -0
  61. package/dist/src/console/tenant-oauth-apps.d.ts +188 -0
  62. package/dist/src/console/tenant-oauth-apps.d.ts.map +1 -0
  63. package/dist/src/console/tenant-oauth-apps.js +152 -0
  64. package/dist/src/console/tenant-oauth-apps.js.map +1 -0
  65. package/dist/src/console/tokens.d.ts +159 -0
  66. package/dist/src/console/tokens.d.ts.map +1 -0
  67. package/dist/src/console/tokens.js +145 -0
  68. package/dist/src/console/tokens.js.map +1 -0
  69. package/dist/src/console/vault.d.ts +188 -0
  70. package/dist/src/console/vault.d.ts.map +1 -0
  71. package/dist/src/console/vault.js +164 -0
  72. package/dist/src/console/vault.js.map +1 -0
  73. package/dist/src/console/workflows.d.ts +243 -0
  74. package/dist/src/console/workflows.d.ts.map +1 -0
  75. package/dist/src/console/workflows.js +205 -0
  76. package/dist/src/console/workflows.js.map +1 -0
  77. package/dist/src/http.d.ts +32 -2
  78. package/dist/src/http.d.ts.map +1 -1
  79. package/dist/src/http.js +11 -2
  80. package/dist/src/http.js.map +1 -1
  81. package/dist/src/types.d.ts +2 -2
  82. package/dist/src/types.d.ts.map +1 -1
  83. package/dist/src/version.js +1 -1
  84. package/package.json +5 -1
@@ -0,0 +1,152 @@
1
+ /**
2
+ * `client.console.tenantOAuthApps.*` — a tenant administrator's own OAuth
3
+ * client overrides (list, upsert, remove) for the apps their tenant connects
4
+ * to.
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
+ * `@w6w/sdk`'s instance-state mechanism pin still applies here exactly as it
10
+ * does to every other namespace (`docs/implementation.md` §MECHANISM PIN —
11
+ * instance state, never globals): this class holds no state of its own beyond
12
+ * the injected host, so two clients in one process never share a credential.
13
+ *
14
+ * **The tenant is never a parameter here.** These three routes are scoped by
15
+ * the caller's own credential (the tenant claim on the bearer) plus a
16
+ * server-side tenant-admin check — unlike the operator family
17
+ * (`GET/PUT/DELETE /tenants/:id/oauth-app…`, `api/admin/tenants.ts:307-309`),
18
+ * which takes the tenant in the path and requires an operator. A `tenant`
19
+ * argument on any method below would be a tenant-selection affordance the
20
+ * server does not offer, so there is none.
21
+ *
22
+ * **Nothing here can read a client secret back.** {@linkcode
23
+ * TenantOAuthAppSummary} carries `hasClientSecret: boolean` and no secret
24
+ * field, mirroring the server's own summary projection
25
+ * (`packages/server/packages/db/repos/tenant_oauth_app.ts:26-37`, whose
26
+ * decrypting sibling `TenantOAuthApp` is entitled to exactly one caller in the
27
+ * BLL). That makes "no method on this namespace can ever resolve a stored
28
+ * secret" a compile-time fact rather than a runtime convention.
29
+ *
30
+ * **Response shapes are flat, no envelope key to peel with `unwrap()`** —
31
+ * mirroring `console/auth.ts:29-32` for this whole family. `list` returns the
32
+ * whole body deliberately, because `callbackUrl` rides beside `configs` and an
33
+ * `unwrap(res, "configs")` would silently drop it; `put` reaches one level in
34
+ * for `body.config`, which is the shape the server answers with (W4).
35
+ *
36
+ * **Wire shapes are planner pins, not reverse-engineered from a merged route.**
37
+ * `plan-B.md` § WIRE PINS W3–W5 fix `GET /tenant/oauth-apps`,
38
+ * `PUT /tenant/oauth-app/:app/:authKey` and
39
+ * `DELETE /tenant/oauth-app/:app/:authKey`; the tenant-scoped handlers are
40
+ * added by a sibling node on the server, against the same pins. The domain
41
+ * rules those handlers enforce already exist and are readable today in
42
+ * `packages/server/packages/bll/tenant-oauth-app.ts` — in particular
43
+ * `effectiveRow` (`:281-296`), which is what makes {@linkcode
44
+ * SetTenantOAuthAppInput}'s omission rule load-bearing rather than cosmetic.
45
+ * See {@linkcode SetTenantOAuthAppInput}.
46
+ *
47
+ * @module
48
+ */
49
+ import { path } from "../http.js";
50
+ /**
51
+ * Serialise {@linkcode SetTenantOAuthAppInput} for the wire: **only the keys
52
+ * actually present**, with `null` preserved as a real value.
53
+ *
54
+ * Written as four explicit `!== undefined` tests rather than a spread or an
55
+ * `Object.entries` loop, for two reasons. It keeps `undefined` off the wire
56
+ * without relying on `JSON.stringify` dropping it (a serializer that
57
+ * normalised `undefined` to `null` would silently wipe a stored credential —
58
+ * see {@linkcode SetTenantOAuthAppInput}), and it is an allowlist: a caller
59
+ * that widens the input type and passes `redirectUri` or `force` cannot get
60
+ * either onto the wire from here, at runtime as well as at compile time.
61
+ *
62
+ * @param input - The caller's partial update.
63
+ * @returns A body carrying exactly the keys `input` set.
64
+ */
65
+ function toSetBody(input) {
66
+ const body = {};
67
+ if (input.clientId !== undefined)
68
+ body.clientId = input.clientId;
69
+ if (input.clientSecret !== undefined)
70
+ body.clientSecret = input.clientSecret;
71
+ if (input.extra !== undefined)
72
+ body.extra = input.extra;
73
+ if (input.disabled !== undefined)
74
+ body.disabled = input.disabled;
75
+ return body;
76
+ }
77
+ /**
78
+ * The `console.tenantOAuthApps` namespace on a `W6wClient` — the caller's own
79
+ * tenant, never a tenant of its choosing.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * const { configs, callbackUrl } = await client.console.tenantOAuthApps.list();
84
+ * // Register `callbackUrl` with the provider — never assemble it client-side.
85
+ * await client.console.tenantOAuthApps.put("sendgrid", "oauth2", { clientId: "abc" });
86
+ * await client.console.tenantOAuthApps.remove("sendgrid", "oauth2");
87
+ * ```
88
+ */
89
+ export class TenantOAuthAppsApi {
90
+ #host;
91
+ /**
92
+ * @param host - The client this namespace issues requests through.
93
+ */
94
+ constructor(host) {
95
+ this.#host = host;
96
+ }
97
+ /**
98
+ * List the caller's tenant's OAuth overrides, plus this host's callback URL.
99
+ *
100
+ * Returns the body VERBATIM rather than unwrapping `configs`: `callbackUrl`
101
+ * rides beside it and is the one value a caller cannot compute for itself.
102
+ *
103
+ * @returns Every override for this tenant, and the server-derived callback URL.
104
+ * @throws {ApiError} `403` when the caller does not administer its tenant.
105
+ */
106
+ async list() {
107
+ const res = await this.#host.request({
108
+ method: "GET",
109
+ path: "/tenant/oauth-apps",
110
+ });
111
+ return res.body;
112
+ }
113
+ /**
114
+ * Create or update one override, sending **only the fields `input` sets**.
115
+ *
116
+ * @param appId - The app id.
117
+ * @param authKey - The app manifest's `oauth2` auth method key.
118
+ * @param input - The fields to set; an omitted field is left untouched server-side.
119
+ * @returns The stored summary (the server answers `201 { config }`). Never carries a secret.
120
+ * @throws {ApiError} `403` when the caller does not administer its tenant;
121
+ * `404 unknown_app` when the app does not exist or does not support a tenant
122
+ * OAuth client; `400 invalid_config`/`invalid_redirect_uri` when the merged
123
+ * row would be an enabled override missing a required field.
124
+ */
125
+ async put(appId, authKey, input) {
126
+ const res = await this.#host.request({
127
+ method: "PUT",
128
+ path: path `/tenant/oauth-app/${appId}/${authKey}`,
129
+ body: toSetBody(input),
130
+ });
131
+ return res.body.config;
132
+ }
133
+ /**
134
+ * Remove one override; the tenant falls back to the host's own OAuth client.
135
+ *
136
+ * Resolves `void`, discarding the server's uninformative `{ok: true}` —
137
+ * mirroring `projects.delete`/`schedules.delete`, not `apps.delete` (which
138
+ * keeps a genuinely informative count).
139
+ *
140
+ * @param appId - The app id.
141
+ * @param authKey - The app manifest's `oauth2` auth method key.
142
+ * @throws {ApiError} `403` when the caller does not administer its tenant;
143
+ * `404 unknown_tenant_oauth_app` when there is no override to remove.
144
+ */
145
+ async remove(appId, authKey) {
146
+ await this.#host.request({
147
+ method: "DELETE",
148
+ path: path `/tenant/oauth-app/${appId}/${authKey}`,
149
+ });
150
+ }
151
+ }
152
+ //# sourceMappingURL=tenant-oauth-apps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-oauth-apps.js","sourceRoot":"","sources":["../../../src/console/tenant-oauth-apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,EAAqB,IAAI,EAAuB,MAAM,YAAY,CAAC;AAyF1E;;;;;;;;;;;;;;GAcG;AACH,SAAS,SAAS,CAAC,KAA6B;IAC9C,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IACjE,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS;QAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;IAC7E,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACxD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,kBAAkB;IACpB,KAAK,CAAsB;IAEpC;;OAEG;IACH,YAAY,IAAyB;QACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAA0B;YAC5D,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,oBAAoB;SAC3B,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,GAAG,CACP,KAAa,EACb,OAAe,EACf,KAA6B;QAE7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoC;YACtE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAA,qBAAqB,KAAK,IAAI,OAAO,EAAE;YACjD,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC;SACvB,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;IACzB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,OAAe;QACzC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAChC,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,IAAI,CAAA,qBAAqB,KAAK,IAAI,OAAO,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * `client.console.tokens.*` — long-lived API tokens for programmatic access
3
+ * (list, create, disable, enable, revoke), relocated from the studio's own
4
+ * 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
+ * **`create`'s plaintext-once invariant is the mechanism this whole domain
16
+ * rests on.** `POST /tokens` is the ONLY response in this entire package that
17
+ * returns a token's plaintext — there is no reveal-later route. That is why
18
+ * {@linkcode CreateTokenResponse} is a SEPARATE type from {@linkcode ApiToken}
19
+ * rather than an optional `secret?` field bolted onto it: `ApiToken` — the
20
+ * return type of every other method here (`list`/`disable`/`enable`/`revoke`)
21
+ * — structurally cannot carry a `secret`, which makes "nothing reachable
22
+ * through those four methods can ever carry a secret" a compile-time fact,
23
+ * not a runtime convention. The server's own `toWire()` doc comment states
24
+ * the same invariant server-side: "never carries the secret, the hash, or
25
+ * internals."
26
+ *
27
+ * Five methods relocate from the studio's own `// API tokens` comment block
28
+ * (`packages/studio/src/api/client.ts:280-303` on the current merged tree) —
29
+ * field-for-field, not redesigned. Studio never sends `account` or
30
+ * `includeRevoked` on `list` (the server's list default already excludes
31
+ * revoked) — per HITL-4's own philosophy ("SDK completeness tracks studio's
32
+ * actual call surface, not the server's full route surface"), neither is
33
+ * added here.
34
+ *
35
+ * None of these methods take a `project` scoping parameter — tokens are
36
+ * account-scoped via the credential alone — so `TokensHost` needs only the
37
+ * transport, mirroring `VarsHost`/`ConnectionsHost`, not `DocumentsHost`.
38
+ *
39
+ * @module
40
+ */
41
+ import { type HttpResponse, type RequestOptions } from "../http.ts";
42
+ /**
43
+ * The slice of `W6wClient` this namespace needs: the transport, and nothing
44
+ * else. Structural rather than a concrete client type, so the namespace stays
45
+ * independently constructible in a test and this module never imports the
46
+ * client back — mirrors `ConnectionsHost` in `./connections.ts`.
47
+ */
48
+ export interface TokensHost {
49
+ /** Perform one request. */
50
+ request<T>(options: RequestOptions): Promise<HttpResponse<T>>;
51
+ }
52
+ /** Lifecycle status of an API token. `revoked` is terminal; `disabled` is reversible. */
53
+ export type ApiTokenStatus = "active" | "disabled" | "revoked";
54
+ /**
55
+ * A long-lived API token for programmatic access — distinct from the studio's
56
+ * own session JWT. **Never carries `secret`** — the server's `toWire()` never
57
+ * puts it on the wire for this shape, and neither does this type. The
58
+ * plaintext is reachable only once, from {@linkcode CreateTokenResponse}.
59
+ */
60
+ export interface ApiToken {
61
+ /** Server-issued id. */
62
+ id: string;
63
+ /** The account this token authenticates as. */
64
+ account: string;
65
+ /** Caller-chosen label. */
66
+ name: string;
67
+ /** Lifecycle status. */
68
+ status: ApiTokenStatus;
69
+ /** ISO-8601 timestamp. */
70
+ createdAt: string;
71
+ /** ISO-8601 timestamp. */
72
+ updatedAt: string;
73
+ /** ISO-8601 timestamp of revocation, or `null` while active/disabled. */
74
+ revokedAt: string | null;
75
+ }
76
+ /**
77
+ * `create`'s result — the token's metadata plus its plaintext secret, shown
78
+ * exactly ONCE. Defined as a type **separate** from {@linkcode ApiToken}, not
79
+ * an optional field on it — see this module's header comment for why that
80
+ * separation is load-bearing rather than a style choice. There is no
81
+ * reveal-later route: if the caller does not capture `secret` here, it is
82
+ * gone.
83
+ */
84
+ export interface CreateTokenResponse {
85
+ /** The created token's metadata. Never carries the secret. */
86
+ token: ApiToken;
87
+ /** The plaintext credential. Shown exactly once — never logged, never re-fetchable. */
88
+ secret: string;
89
+ }
90
+ /**
91
+ * The `console.tokens` namespace on a `W6wClient`.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const tokens = await client.console.tokens.list();
96
+ * const { token, secret } = await client.console.tokens.create("ci-deploy");
97
+ * console.log(secret); // shown exactly once — capture it now or it is gone
98
+ * await client.console.tokens.disable(token.id);
99
+ * await client.console.tokens.enable(token.id);
100
+ * await client.console.tokens.revoke(token.id);
101
+ * ```
102
+ */
103
+ export declare class TokensApi {
104
+ #private;
105
+ /**
106
+ * @param host - The client this namespace issues requests through.
107
+ */
108
+ constructor(host: TokensHost);
109
+ /**
110
+ * List the account's tokens. Excludes revoked tokens (the server's default);
111
+ * this method does not expose a parameter to include them, matching
112
+ * studio's own call surface.
113
+ *
114
+ * @returns The tokens, unwrapped from the `tokens` envelope. Never carries `secret`.
115
+ */
116
+ list(): Promise<ApiToken[]>;
117
+ /**
118
+ * Create a token. **Returns the plaintext secret exactly once** — there is
119
+ * no reveal-later route, so a caller that does not capture it here has
120
+ * permanently lost it.
121
+ *
122
+ * **No envelope key to peel — the whole body IS `{token, secret}`.** Typed
123
+ * directly as `request<CreateTokenResponse>(...)`, returning `res.body`,
124
+ * mirroring `console.connections.test`'s/`console.reliability.list`'s
125
+ * established "no envelope key" pattern. `unwrap()` is deliberately not
126
+ * called here: there is no single key to unwrap.
127
+ *
128
+ * @param name - Caller-chosen label.
129
+ * @returns The created token's metadata plus its one-time plaintext secret.
130
+ * @throws {ApiError} `400 invalid_name`.
131
+ */
132
+ create(name: string): Promise<CreateTokenResponse>;
133
+ /**
134
+ * Disable a token. Reversible — see {@linkcode enable}.
135
+ *
136
+ * @param id - The token id.
137
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
138
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`.
139
+ */
140
+ disable(id: string): Promise<ApiToken>;
141
+ /**
142
+ * Re-enable a disabled token.
143
+ *
144
+ * @param id - The token id.
145
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
146
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`; `409 invalid_transition` when the
147
+ * token is revoked (revoke is terminal).
148
+ */
149
+ enable(id: string): Promise<ApiToken>;
150
+ /**
151
+ * Revoke a token. Terminal — a revoked token cannot be re-enabled.
152
+ *
153
+ * @param id - The token id.
154
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
155
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`.
156
+ */
157
+ revoke(id: string): Promise<ApiToken>;
158
+ }
159
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../src/console/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAQ,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,2BAA2B;IAC3B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,KAAK,EAAE,QAAQ,CAAC;IAChB,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAS;;IAGpB;;OAEG;gBACS,IAAI,EAAE,UAAU;IAI5B;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAKjC;;;;;;;;;;;;;;OAcG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IASxD;;;;;;OAMG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAS5C;;;;;;;OAOG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAS3C;;;;;;OAMG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAQ5C"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * `client.console.tokens.*` — long-lived API tokens for programmatic access
3
+ * (list, create, disable, enable, revoke), relocated from the studio's own
4
+ * 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
+ * **`create`'s plaintext-once invariant is the mechanism this whole domain
16
+ * rests on.** `POST /tokens` is the ONLY response in this entire package that
17
+ * returns a token's plaintext — there is no reveal-later route. That is why
18
+ * {@linkcode CreateTokenResponse} is a SEPARATE type from {@linkcode ApiToken}
19
+ * rather than an optional `secret?` field bolted onto it: `ApiToken` — the
20
+ * return type of every other method here (`list`/`disable`/`enable`/`revoke`)
21
+ * — structurally cannot carry a `secret`, which makes "nothing reachable
22
+ * through those four methods can ever carry a secret" a compile-time fact,
23
+ * not a runtime convention. The server's own `toWire()` doc comment states
24
+ * the same invariant server-side: "never carries the secret, the hash, or
25
+ * internals."
26
+ *
27
+ * Five methods relocate from the studio's own `// API tokens` comment block
28
+ * (`packages/studio/src/api/client.ts:280-303` on the current merged tree) —
29
+ * field-for-field, not redesigned. Studio never sends `account` or
30
+ * `includeRevoked` on `list` (the server's list default already excludes
31
+ * revoked) — per HITL-4's own philosophy ("SDK completeness tracks studio's
32
+ * actual call surface, not the server's full route surface"), neither is
33
+ * added here.
34
+ *
35
+ * None of these methods take a `project` scoping parameter — tokens are
36
+ * account-scoped via the credential alone — so `TokensHost` needs only the
37
+ * transport, mirroring `VarsHost`/`ConnectionsHost`, not `DocumentsHost`.
38
+ *
39
+ * @module
40
+ */
41
+ import { path } from "../http.js";
42
+ import { unwrap } from "../types.js";
43
+ /**
44
+ * The `console.tokens` namespace on a `W6wClient`.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const tokens = await client.console.tokens.list();
49
+ * const { token, secret } = await client.console.tokens.create("ci-deploy");
50
+ * console.log(secret); // shown exactly once — capture it now or it is gone
51
+ * await client.console.tokens.disable(token.id);
52
+ * await client.console.tokens.enable(token.id);
53
+ * await client.console.tokens.revoke(token.id);
54
+ * ```
55
+ */
56
+ export class TokensApi {
57
+ #host;
58
+ /**
59
+ * @param host - The client this namespace issues requests through.
60
+ */
61
+ constructor(host) {
62
+ this.#host = host;
63
+ }
64
+ /**
65
+ * List the account's tokens. Excludes revoked tokens (the server's default);
66
+ * this method does not expose a parameter to include them, matching
67
+ * studio's own call surface.
68
+ *
69
+ * @returns The tokens, unwrapped from the `tokens` envelope. Never carries `secret`.
70
+ */
71
+ async list() {
72
+ const res = await this.#host.request({ method: "GET", path: "/tokens" });
73
+ return unwrap(res, "tokens");
74
+ }
75
+ /**
76
+ * Create a token. **Returns the plaintext secret exactly once** — there is
77
+ * no reveal-later route, so a caller that does not capture it here has
78
+ * permanently lost it.
79
+ *
80
+ * **No envelope key to peel — the whole body IS `{token, secret}`.** Typed
81
+ * directly as `request<CreateTokenResponse>(...)`, returning `res.body`,
82
+ * mirroring `console.connections.test`'s/`console.reliability.list`'s
83
+ * established "no envelope key" pattern. `unwrap()` is deliberately not
84
+ * called here: there is no single key to unwrap.
85
+ *
86
+ * @param name - Caller-chosen label.
87
+ * @returns The created token's metadata plus its one-time plaintext secret.
88
+ * @throws {ApiError} `400 invalid_name`.
89
+ */
90
+ async create(name) {
91
+ const res = await this.#host.request({
92
+ method: "POST",
93
+ path: "/tokens",
94
+ body: { name },
95
+ });
96
+ return res.body;
97
+ }
98
+ /**
99
+ * Disable a token. Reversible — see {@linkcode enable}.
100
+ *
101
+ * @param id - The token id.
102
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
103
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`.
104
+ */
105
+ async disable(id) {
106
+ const res = await this.#host.request({
107
+ method: "POST",
108
+ path: path `/tokens/${id}/disable`,
109
+ body: {},
110
+ });
111
+ return unwrap(res, "token");
112
+ }
113
+ /**
114
+ * Re-enable a disabled token.
115
+ *
116
+ * @param id - The token id.
117
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
118
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`; `409 invalid_transition` when the
119
+ * token is revoked (revoke is terminal).
120
+ */
121
+ async enable(id) {
122
+ const res = await this.#host.request({
123
+ method: "POST",
124
+ path: path `/tokens/${id}/enable`,
125
+ body: {},
126
+ });
127
+ return unwrap(res, "token");
128
+ }
129
+ /**
130
+ * Revoke a token. Terminal — a revoked token cannot be re-enabled.
131
+ *
132
+ * @param id - The token id.
133
+ * @returns The updated token, unwrapped from the `token` envelope. Never carries `secret`.
134
+ * @throws {ApiError} `404 unknown_token`/`unknown_account`.
135
+ */
136
+ async revoke(id) {
137
+ const res = await this.#host.request({
138
+ method: "POST",
139
+ path: path `/tokens/${id}/revoke`,
140
+ body: {},
141
+ });
142
+ return unwrap(res, "token");
143
+ }
144
+ }
145
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/console/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAqB,IAAI,EAAuB,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAsDrC;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,SAAS;IACX,KAAK,CAAa;IAE3B;;OAEG;IACH,YAAY,IAAgB;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAClF,OAAO,MAAM,CAAa,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB;YACxD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,EAAE,IAAI,EAAE;SACf,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAA,WAAW,EAAE,UAAU;YACjC,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QACH,OAAO,MAAM,CAAW,GAAG,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAA,WAAW,EAAE,SAAS;YAChC,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QACH,OAAO,MAAM,CAAW,GAAG,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAA,WAAW,EAAE,SAAS;YAChC,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QACH,OAAO,MAAM,CAAW,GAAG,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;CACF"}
@@ -0,0 +1,188 @@
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 { type HttpResponse, type RequestOptions } from "../http.ts";
42
+ /**
43
+ * The slice of `W6wClient` this namespace needs: the transport, and nothing
44
+ * else. Structural rather than a concrete client type, so the namespace stays
45
+ * independently constructible in a test and this module never imports the
46
+ * client back — mirrors `ConnectionsHost` in `./connections.ts`.
47
+ */
48
+ export interface VaultHost {
49
+ /** Perform one request. */
50
+ request<T>(options: RequestOptions): Promise<HttpResponse<T>>;
51
+ }
52
+ /**
53
+ * Public projection of a stored vault secret. **`value` is deliberately
54
+ * absent** — the server never puts a secret's plaintext on the wire for
55
+ * `list`/`get`/`create`/`update`, and declaring the field here would promise a
56
+ * caller something that can never arrive.
57
+ */
58
+ export interface VaultSecretSummary {
59
+ /** Server-issued id, `sec_…`. */
60
+ id: string;
61
+ /** Caller-chosen name, matching `^[a-z_][a-z0-9_]*$`. */
62
+ name: string;
63
+ /** Free-text description; `""` when unset. */
64
+ description: string;
65
+ /** ISO-8601 timestamp. */
66
+ createdAt: string;
67
+ /** ISO-8601 timestamp. */
68
+ updatedAt: string;
69
+ }
70
+ /**
71
+ * An at-rest ciphertext envelope for one ad-hoc secret value, produced by
72
+ * {@linkcode VaultApi.seal}. Field-for-field identical to
73
+ * `packages/ui/src/types.ts`'s `SecretValue` shape, defined locally here
74
+ * rather than imported from `@w6w/ui` — this SDK has no dependency on
75
+ * `packages/ui` and must not gain one (wrong dependency direction for a
76
+ * published SDK). TypeScript's structural typing makes this value satisfy
77
+ * `@w6w/ui`'s `ExpressionOptions.sealSecret` prop shape at a studio call site
78
+ * with no shared import needed.
79
+ */
80
+ export interface SecretValue {
81
+ type: "secret";
82
+ /** Base64-encoded ciphertext. */
83
+ ciphertext: string;
84
+ /** Base64-encoded initialization vector. */
85
+ iv: string;
86
+ }
87
+ /**
88
+ * The `console.vault` namespace on a `W6wClient`.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * const secrets = await client.console.vault.list();
93
+ * const created = await client.console.vault.create({ name: "openai_key", value: "sk-…" });
94
+ * await client.console.vault.update(created.id, { description: "Prod key" });
95
+ * const sealed = await client.console.vault.seal("sk-live-…");
96
+ * await client.console.vault.delete(created.id);
97
+ * ```
98
+ */
99
+ export declare class VaultApi {
100
+ #private;
101
+ /**
102
+ * @param host - The client this namespace issues requests through.
103
+ */
104
+ constructor(host: VaultHost);
105
+ /**
106
+ * List the account's vault secrets.
107
+ *
108
+ * @returns The secrets, unwrapped from the `secrets` envelope. Never
109
+ * carries `value`.
110
+ */
111
+ list(): Promise<VaultSecretSummary[]>;
112
+ /**
113
+ * Fetch one secret's metadata.
114
+ *
115
+ * **Zero studio callers today** — built for SDK completeness only. No 404
116
+ * special-casing — propagates as `ApiError` like every other "get" in this
117
+ * package except `console.schedules.get`, which has its own documented,
118
+ * unrelated exception.
119
+ *
120
+ * @param id - The `sec_…` id.
121
+ * @returns The secret, unwrapped from the `secret` envelope. Never carries `value`.
122
+ * @throws {ApiError} `404 unknown_secret` when there is no such id.
123
+ */
124
+ get(id: string): Promise<VaultSecretSummary>;
125
+ /**
126
+ * Create a secret.
127
+ *
128
+ * `value` is opaque — forwarded verbatim, never inspected, logged, or
129
+ * transformed.
130
+ *
131
+ * @param body - `name` (unique, matches `^[a-z_][a-z0-9_]*$`), `value` (the
132
+ * plaintext to store), and an optional `description`.
133
+ * @returns The created secret, unwrapped from the `secret` envelope (the
134
+ * server answers `201`). Never carries `value`.
135
+ * @throws {ApiError} `400 invalid_name`/`invalid_value`/`invalid_description`; `409 secret_exists`.
136
+ */
137
+ create(body: {
138
+ name: string;
139
+ value: string;
140
+ description?: string;
141
+ }): Promise<VaultSecretSummary>;
142
+ /**
143
+ * Update a secret: replace its value and/or its description.
144
+ *
145
+ * `value` is opaque — forwarded verbatim, never inspected, logged, or
146
+ * transformed, same discipline as {@linkcode create}.
147
+ *
148
+ * @param id - The `sec_…` id.
149
+ * @param body - `value` and/or `description`, forwarded verbatim.
150
+ * @returns The updated secret, unwrapped from the `secret` envelope. Never carries `value`.
151
+ * @throws {ApiError} `400 invalid_value`/`invalid_description`; `404 unknown_secret`.
152
+ */
153
+ update(id: string, body: {
154
+ value?: string;
155
+ description?: string;
156
+ }): Promise<VaultSecretSummary>;
157
+ /**
158
+ * Delete a secret.
159
+ *
160
+ * Returns nothing: the server's `{ok: true}` carries no information a
161
+ * caller can use, mirroring `console.projects.delete`/
162
+ * `console.schedules.delete`/`console.connections.delete` in this same
163
+ * package (NOT `console.apps.delete`, which is the one documented
164
+ * exception) — vault delete has no such value to preserve.
165
+ *
166
+ * @param id - The `sec_…` id.
167
+ * @throws {ApiError} `404 unknown_secret` when there is no such id.
168
+ */
169
+ delete(id: string): Promise<void>;
170
+ /**
171
+ * Encrypt an ad-hoc secret value into an at-rest ciphertext envelope,
172
+ * without storing it.
173
+ *
174
+ * **An encrypt-only oracle — there is no matching decrypt route.** The
175
+ * server's own header comment states the security property directly: "an
176
+ * authed caller learns nothing they didn't provide." `value` is opaque —
177
+ * forwarded verbatim, never inspected, logged, or transformed. **No
178
+ * envelope key to peel on the request side** — the body IS `{ value }` —
179
+ * but the *response* IS enveloped under `sealed`, unlike `console.
180
+ * connections.test`'s/`console.reliability.list`'s whole-body responses.
181
+ *
182
+ * @param value - The plaintext to seal. Never logged, never echoed back.
183
+ * @returns The ciphertext envelope, unwrapped from the `sealed` envelope.
184
+ * @throws {ApiError} `400 invalid_value` when `value` is empty.
185
+ */
186
+ seal(value: string): Promise<SecretValue>;
187
+ }
188
+ //# sourceMappingURL=vault.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../../src/console/vault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAQ,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,QAAQ;;IAGnB;;OAEG;gBACS,IAAI,EAAE,SAAS;IAI3B;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAK3C;;;;;;;;;;;OAWG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAKlD;;;;;;;;;;;OAWG;IACG,MAAM,CACV,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1D,OAAO,CAAC,kBAAkB,CAAC;IAK9B;;;;;;;;;;OAUG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7C,OAAO,CAAC,kBAAkB,CAAC;IAS9B;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;;;;;;;;;;OAeG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAQhD"}