@w6w/sdk 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.
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/mod.d.ts +37 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +51 -0
- package/dist/mod.js.map +1 -0
- package/dist/src/client.d.ts +134 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/client.js +165 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/config.d.ts +151 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +161 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/connections.d.ts +58 -0
- package/dist/src/connections.d.ts.map +1 -0
- package/dist/src/connections.js +52 -0
- package/dist/src/connections.js.map +1 -0
- package/dist/src/documents.d.ts +168 -0
- package/dist/src/documents.d.ts.map +1 -0
- package/dist/src/documents.js +178 -0
- package/dist/src/documents.js.map +1 -0
- package/dist/src/env.d.ts +61 -0
- package/dist/src/env.d.ts.map +1 -0
- package/dist/src/env.js +73 -0
- package/dist/src/env.js.map +1 -0
- package/dist/src/errors.d.ts +79 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +88 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/http.d.ts +130 -0
- package/dist/src/http.d.ts.map +1 -0
- package/dist/src/http.js +150 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/me.d.ts +53 -0
- package/dist/src/me.d.ts.map +1 -0
- package/dist/src/me.js +77 -0
- package/dist/src/me.js.map +1 -0
- package/dist/src/run.d.ts +92 -0
- package/dist/src/run.d.ts.map +1 -0
- package/dist/src/run.js +83 -0
- package/dist/src/run.js.map +1 -0
- package/dist/src/types.d.ts +362 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +109 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/vars.d.ts +149 -0
- package/dist/src/vars.d.ts.map +1 -0
- package/dist/src/vars.js +149 -0
- package/dist/src/vars.js.map +1 -0
- package/dist/src/version.d.ts +14 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +14 -0
- package/dist/src/version.js.map +1 -0
- package/dist/src/workflows.d.ts +180 -0
- package/dist/src/workflows.d.ts.map +1 -0
- package/dist/src/workflows.js +160 -0
- package/dist/src/workflows.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution: what server, what credential, what project.
|
|
3
|
+
*
|
|
4
|
+
* This module turns whatever the caller supplied — plus the environment, read
|
|
5
|
+
* through the single seam in `src/env.ts` — into one plain {@linkcode
|
|
6
|
+
* ResolvedConfig} value. It is resolved **once, at client construction**, and
|
|
7
|
+
* handed to the transport; nothing downstream re-reads the environment.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The API's base path, from the shared contract's `basePath`
|
|
13
|
+
* (`packages/wrappers/endpoints.json`). It is appended to the configured
|
|
14
|
+
* origin by {@linkcode joinBaseUrl}; users never type it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const BASE_PATH = "/api";
|
|
17
|
+
/**
|
|
18
|
+
* A `fetch`-shaped function.
|
|
19
|
+
*
|
|
20
|
+
* This is the injection seam every test in this package runs against: no test
|
|
21
|
+
* may require a live server (`docs/implementation.md` §9). It is
|
|
22
|
+
* constructor-injected for the same reason the credential is — a module-patched
|
|
23
|
+
* global cannot be exercised two different ways in one process.
|
|
24
|
+
*
|
|
25
|
+
* `globalThis.fetch` satisfies it (a wider parameter type is assignable to a
|
|
26
|
+
* narrower one), while a fake only has to accept a URL string.
|
|
27
|
+
*/
|
|
28
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
29
|
+
/** Constructor options for a client. Every field is optional. */
|
|
30
|
+
export interface W6wClientOptions {
|
|
31
|
+
/**
|
|
32
|
+
* The **origin** of the w6w server, e.g. `https://api.example.com`. The base
|
|
33
|
+
* path (`/api`) is appended for you and is never doubled. It must be an
|
|
34
|
+
* absolute `http(s)` URL with a host: a relative value like `/api` is a
|
|
35
|
+
* browser same-origin assumption with no meaning in a library, and is
|
|
36
|
+
* rejected at construction rather than misreported as an outage later.
|
|
37
|
+
* Overrides `W6W_BASE_URL`.
|
|
38
|
+
*/
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
/** Bearer token, sent on every request. Overrides `W6W_TOKEN`. */
|
|
41
|
+
token?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Default project id for the project-scoped operations — `documents.*` and
|
|
44
|
+
* `workflows.list`, which read it too.
|
|
45
|
+
* Omitted, the server resolves the account's default project. There is no
|
|
46
|
+
* environment variable for this and no `project` on any `vars.*` operation —
|
|
47
|
+
* vars are not project-scoped (`docs/implementation.md` §7).
|
|
48
|
+
*/
|
|
49
|
+
project?: string;
|
|
50
|
+
/** Transport override. Defaults to `globalThis.fetch`. */
|
|
51
|
+
fetch?: FetchLike;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Configuration after resolution — the value the transport actually runs on.
|
|
55
|
+
*
|
|
56
|
+
* Held as **instance** state on the client, never in a module-level variable:
|
|
57
|
+
* two clients in one process must be able to hold different credentials and
|
|
58
|
+
* point at different servers with no interference (`docs/implementation.md` §2).
|
|
59
|
+
*/
|
|
60
|
+
export interface ResolvedConfig {
|
|
61
|
+
/**
|
|
62
|
+
* Fully joined base, e.g. `https://api.example.com/api`. Never
|
|
63
|
+
* trailing-slashed, and never relative — {@linkcode joinBaseUrl} rejects a
|
|
64
|
+
* value that is not an absolute `http(s)` URL with a host.
|
|
65
|
+
*/
|
|
66
|
+
readonly baseUrl: string;
|
|
67
|
+
/** The bearer token, or `null` when none was configured. */
|
|
68
|
+
readonly token: string | null;
|
|
69
|
+
/** Default project id, or `null`. */
|
|
70
|
+
readonly project: string | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Validate a configured origin and join it with the API base path.
|
|
74
|
+
*
|
|
75
|
+
* **This is the one and only base-URL code path.** {@linkcode resolveConfig}
|
|
76
|
+
* calls this function and normalises nothing itself, so a caller who imports
|
|
77
|
+
* the helper gets exactly the answer their client will use — including the same
|
|
78
|
+
* errors. A helper that were merely *similar* to the client's path (skipping the
|
|
79
|
+
* whitespace trim, say) would answer differently for the same input, which is
|
|
80
|
+
* worse than having no helper at all. The python lane found and fixed the
|
|
81
|
+
* identical divergence in its own draft; this mirrors its resolution.
|
|
82
|
+
*
|
|
83
|
+
* The join rule is pinned by `docs/implementation.md` §2 and mirrors the house
|
|
84
|
+
* helper that the operator console already uses against this same API, so all
|
|
85
|
+
* clients agree on what `W6W_BASE_URL` means:
|
|
86
|
+
*
|
|
87
|
+
* 1. strip surrounding whitespace, then **all** trailing slashes;
|
|
88
|
+
* 2. reject anything that is not an absolute `http`/`https` URL with a host;
|
|
89
|
+
* 3. if the result already ends with the base path, use it as-is — **never
|
|
90
|
+
* double it**;
|
|
91
|
+
* 4. otherwise append the base path.
|
|
92
|
+
*
|
|
93
|
+
* ```
|
|
94
|
+
* https://api.example.com → https://api.example.com/api
|
|
95
|
+
* https://api.example.com/ → https://api.example.com/api
|
|
96
|
+
* https://api.example.com/// → https://api.example.com/api
|
|
97
|
+
* https://api.example.com/api → https://api.example.com/api
|
|
98
|
+
* https://api.example.com/api/ → https://api.example.com/api
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* Step 2 exists because a **relative** base URL has to fail *here*, as
|
|
102
|
+
* configuration, with a message about configuration. Blank-is-absent
|
|
103
|
+
* (`src/env.ts`) already stops `""` from joining to the relative `"/api"`; with
|
|
104
|
+
* no absoluteness check, `W6W_BASE_URL=/foo` walked straight past that guard to
|
|
105
|
+
* `"/foo/api"` and then failed on the first request as "the server may be down"
|
|
106
|
+
* — the same hole, reopened by another route, and misdiagnosed. Closing only one
|
|
107
|
+
* of the two leaves the other open.
|
|
108
|
+
*
|
|
109
|
+
* @param origin - The configured origin. Surrounding whitespace and trailing slashes are tolerated.
|
|
110
|
+
* @returns The joined base URL.
|
|
111
|
+
* @throws {ConfigError} When the origin is blank, relative, hostless or not `http(s)`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function joinBaseUrl(origin: string): string;
|
|
114
|
+
/**
|
|
115
|
+
* Resolve constructor options and the environment into one config value.
|
|
116
|
+
*
|
|
117
|
+
* Precedence is **explicit argument > environment variable**, always; there is
|
|
118
|
+
* no default base URL. An explicitly passed empty string is an *explicit*
|
|
119
|
+
* value, not "unset" — it does not fall through to the environment, and an
|
|
120
|
+
* empty base URL is a configuration error either way. Only an absent
|
|
121
|
+
* (`undefined`) argument consults the environment.
|
|
122
|
+
*
|
|
123
|
+
* An **empty or whitespace-only environment variable is absent** and falls
|
|
124
|
+
* through (see `src/env.ts`), so `W6W_BASE_URL=`, `W6W_BASE_URL=" "` and an
|
|
125
|
+
* unset `W6W_BASE_URL` all end here, in the same configuration error — never in
|
|
126
|
+
* a relative `"/api"`.
|
|
127
|
+
*
|
|
128
|
+
* @param options - Constructor options; `fetch` is ignored here (the client owns it).
|
|
129
|
+
* @returns The resolved configuration.
|
|
130
|
+
* @throws {ConfigError} When no usable base URL was supplied, naming `W6W_BASE_URL`.
|
|
131
|
+
*/
|
|
132
|
+
export declare function resolveConfig(options?: W6wClientOptions): ResolvedConfig;
|
|
133
|
+
/**
|
|
134
|
+
* The token, or a {@linkcode ConfigError} naming `W6W_TOKEN`.
|
|
135
|
+
*
|
|
136
|
+
* A client may be *constructed* without a token so that a CLI's `--help` and
|
|
137
|
+
* `--version` work offline; the error surfaces on the first request instead.
|
|
138
|
+
* There are no anonymous operations in this surface
|
|
139
|
+
* (`docs/implementation.md` §2).
|
|
140
|
+
*
|
|
141
|
+
* A blank token counts as no token, for the same reason a blank base URL does:
|
|
142
|
+
* `W6W_TOKEN=` is how a shell or a Dockerfile spells "I meant to set this and
|
|
143
|
+
* did not", and `Authorization: Bearer ` would turn that into an opaque 401
|
|
144
|
+
* instead of the one message that explains it.
|
|
145
|
+
*
|
|
146
|
+
* @param config - The resolved configuration.
|
|
147
|
+
* @returns The configured token, verbatim.
|
|
148
|
+
* @throws {ConfigError} When no non-blank token is configured.
|
|
149
|
+
*/
|
|
150
|
+
export declare function requireToken(config: ResolvedConfig): string;
|
|
151
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH;;;;GAIG;AACH,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAuBlD;AAkBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,gBAAqB,GAAG,cAAc,CAS5E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAS3D"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution: what server, what credential, what project.
|
|
3
|
+
*
|
|
4
|
+
* This module turns whatever the caller supplied — plus the environment, read
|
|
5
|
+
* through the single seam in `src/env.ts` — into one plain {@linkcode
|
|
6
|
+
* ResolvedConfig} value. It is resolved **once, at client construction**, and
|
|
7
|
+
* handed to the transport; nothing downstream re-reads the environment.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { ENV_BASE_URL, ENV_TOKEN, readEnv } from "./env.js";
|
|
12
|
+
import { ConfigError } from "./errors.js";
|
|
13
|
+
/**
|
|
14
|
+
* The API's base path, from the shared contract's `basePath`
|
|
15
|
+
* (`packages/wrappers/endpoints.json`). It is appended to the configured
|
|
16
|
+
* origin by {@linkcode joinBaseUrl}; users never type it.
|
|
17
|
+
*/
|
|
18
|
+
export const BASE_PATH = "/api";
|
|
19
|
+
/**
|
|
20
|
+
* An absolute `http(s)` origin, spelled with a real authority.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately checked *before* `new URL`, because the WHATWG parser silently
|
|
23
|
+
* repairs the one spelling this rule most needs to catch: `new URL("http:///foo")`
|
|
24
|
+
* does **not** fail and does **not** yield an empty host — it collapses the extra
|
|
25
|
+
* slash and resolves to `http://foo/`, so a host check alone would accept a
|
|
26
|
+
* hostless value and then request a different server than the one the user typed.
|
|
27
|
+
* Measured in the api container, not assumed. The pattern therefore requires the
|
|
28
|
+
* authority to start with a character that is not a slash, backslash, `?` or `#`.
|
|
29
|
+
*/
|
|
30
|
+
const ABSOLUTE_HTTP_ORIGIN = /^https?:\/\/[^/\\?#]/i;
|
|
31
|
+
/**
|
|
32
|
+
* Validate a configured origin and join it with the API base path.
|
|
33
|
+
*
|
|
34
|
+
* **This is the one and only base-URL code path.** {@linkcode resolveConfig}
|
|
35
|
+
* calls this function and normalises nothing itself, so a caller who imports
|
|
36
|
+
* the helper gets exactly the answer their client will use — including the same
|
|
37
|
+
* errors. A helper that were merely *similar* to the client's path (skipping the
|
|
38
|
+
* whitespace trim, say) would answer differently for the same input, which is
|
|
39
|
+
* worse than having no helper at all. The python lane found and fixed the
|
|
40
|
+
* identical divergence in its own draft; this mirrors its resolution.
|
|
41
|
+
*
|
|
42
|
+
* The join rule is pinned by `docs/implementation.md` §2 and mirrors the house
|
|
43
|
+
* helper that the operator console already uses against this same API, so all
|
|
44
|
+
* clients agree on what `W6W_BASE_URL` means:
|
|
45
|
+
*
|
|
46
|
+
* 1. strip surrounding whitespace, then **all** trailing slashes;
|
|
47
|
+
* 2. reject anything that is not an absolute `http`/`https` URL with a host;
|
|
48
|
+
* 3. if the result already ends with the base path, use it as-is — **never
|
|
49
|
+
* double it**;
|
|
50
|
+
* 4. otherwise append the base path.
|
|
51
|
+
*
|
|
52
|
+
* ```
|
|
53
|
+
* https://api.example.com → https://api.example.com/api
|
|
54
|
+
* https://api.example.com/ → https://api.example.com/api
|
|
55
|
+
* https://api.example.com/// → https://api.example.com/api
|
|
56
|
+
* https://api.example.com/api → https://api.example.com/api
|
|
57
|
+
* https://api.example.com/api/ → https://api.example.com/api
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* Step 2 exists because a **relative** base URL has to fail *here*, as
|
|
61
|
+
* configuration, with a message about configuration. Blank-is-absent
|
|
62
|
+
* (`src/env.ts`) already stops `""` from joining to the relative `"/api"`; with
|
|
63
|
+
* no absoluteness check, `W6W_BASE_URL=/foo` walked straight past that guard to
|
|
64
|
+
* `"/foo/api"` and then failed on the first request as "the server may be down"
|
|
65
|
+
* — the same hole, reopened by another route, and misdiagnosed. Closing only one
|
|
66
|
+
* of the two leaves the other open.
|
|
67
|
+
*
|
|
68
|
+
* @param origin - The configured origin. Surrounding whitespace and trailing slashes are tolerated.
|
|
69
|
+
* @returns The joined base URL.
|
|
70
|
+
* @throws {ConfigError} When the origin is blank, relative, hostless or not `http(s)`.
|
|
71
|
+
*/
|
|
72
|
+
export function joinBaseUrl(origin) {
|
|
73
|
+
// Surrounding whitespace is stripped before the emptiness test so a blank
|
|
74
|
+
// explicit argument fails the same way a blank environment variable does — an
|
|
75
|
+
// env file's stray "\n" must not become part of the origin.
|
|
76
|
+
const trimmed = origin.trim().replace(/\/+$/, "");
|
|
77
|
+
if (trimmed.length === 0) {
|
|
78
|
+
throw new ConfigError("No w6w base URL is configured. Pass one to the client " +
|
|
79
|
+
'(new W6wClient({ baseUrl: "https://api.example.com" })) or set the ' +
|
|
80
|
+
`${ENV_BASE_URL} environment variable. It holds the server's origin — the ` +
|
|
81
|
+
`${BASE_PATH} base path is appended for you.`);
|
|
82
|
+
}
|
|
83
|
+
if (!ABSOLUTE_HTTP_ORIGIN.test(trimmed) || !parses(trimmed)) {
|
|
84
|
+
throw new ConfigError(`The w6w base URL "${trimmed}" is not an absolute http(s) URL. ` +
|
|
85
|
+
`${ENV_BASE_URL} holds an ORIGIN, e.g. "https://api.example.com" — scheme and host, ` +
|
|
86
|
+
`with the ${BASE_PATH} base path appended for you. A relative or hostless value ` +
|
|
87
|
+
"cannot be requested and would fail later as a connection problem rather than as " +
|
|
88
|
+
"the configuration mistake it is.");
|
|
89
|
+
}
|
|
90
|
+
return trimmed.endsWith(BASE_PATH) ? trimmed : `${trimmed}${BASE_PATH}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Does the runtime's URL parser accept this origin at all?
|
|
94
|
+
*
|
|
95
|
+
* The pattern above settles *shape* (scheme, `//`, a real authority); this
|
|
96
|
+
* settles the rest — an out-of-range port, a malformed IPv6 literal, a host the
|
|
97
|
+
* parser rejects. Both have to hold, and neither subsumes the other.
|
|
98
|
+
*/
|
|
99
|
+
function parses(origin) {
|
|
100
|
+
try {
|
|
101
|
+
new URL(origin);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resolve constructor options and the environment into one config value.
|
|
110
|
+
*
|
|
111
|
+
* Precedence is **explicit argument > environment variable**, always; there is
|
|
112
|
+
* no default base URL. An explicitly passed empty string is an *explicit*
|
|
113
|
+
* value, not "unset" — it does not fall through to the environment, and an
|
|
114
|
+
* empty base URL is a configuration error either way. Only an absent
|
|
115
|
+
* (`undefined`) argument consults the environment.
|
|
116
|
+
*
|
|
117
|
+
* An **empty or whitespace-only environment variable is absent** and falls
|
|
118
|
+
* through (see `src/env.ts`), so `W6W_BASE_URL=`, `W6W_BASE_URL=" "` and an
|
|
119
|
+
* unset `W6W_BASE_URL` all end here, in the same configuration error — never in
|
|
120
|
+
* a relative `"/api"`.
|
|
121
|
+
*
|
|
122
|
+
* @param options - Constructor options; `fetch` is ignored here (the client owns it).
|
|
123
|
+
* @returns The resolved configuration.
|
|
124
|
+
* @throws {ConfigError} When no usable base URL was supplied, naming `W6W_BASE_URL`.
|
|
125
|
+
*/
|
|
126
|
+
export function resolveConfig(options = {}) {
|
|
127
|
+
return {
|
|
128
|
+
// Every normalisation, the emptiness test and the absoluteness check live in
|
|
129
|
+
// `joinBaseUrl` — one code path, so the exported helper and the client can
|
|
130
|
+
// never answer differently for the same input.
|
|
131
|
+
baseUrl: joinBaseUrl(options.baseUrl ?? readEnv(ENV_BASE_URL) ?? ""),
|
|
132
|
+
token: options.token ?? readEnv(ENV_TOKEN) ?? null,
|
|
133
|
+
project: options.project ?? null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The token, or a {@linkcode ConfigError} naming `W6W_TOKEN`.
|
|
138
|
+
*
|
|
139
|
+
* A client may be *constructed* without a token so that a CLI's `--help` and
|
|
140
|
+
* `--version` work offline; the error surfaces on the first request instead.
|
|
141
|
+
* There are no anonymous operations in this surface
|
|
142
|
+
* (`docs/implementation.md` §2).
|
|
143
|
+
*
|
|
144
|
+
* A blank token counts as no token, for the same reason a blank base URL does:
|
|
145
|
+
* `W6W_TOKEN=` is how a shell or a Dockerfile spells "I meant to set this and
|
|
146
|
+
* did not", and `Authorization: Bearer ` would turn that into an opaque 401
|
|
147
|
+
* instead of the one message that explains it.
|
|
148
|
+
*
|
|
149
|
+
* @param config - The resolved configuration.
|
|
150
|
+
* @returns The configured token, verbatim.
|
|
151
|
+
* @throws {ConfigError} When no non-blank token is configured.
|
|
152
|
+
*/
|
|
153
|
+
export function requireToken(config) {
|
|
154
|
+
if (config.token === null || config.token.trim().length === 0) {
|
|
155
|
+
throw new ConfigError("No w6w API token is configured. Pass one to the client " +
|
|
156
|
+
'(new W6wClient({ token: "…" })) or set the ' +
|
|
157
|
+
`${ENV_TOKEN} environment variable. Every w6w API operation is authenticated.`);
|
|
158
|
+
}
|
|
159
|
+
return config.token;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AA4DhC;;;;;;;;;;GAUG;AACH,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,0EAA0E;IAC1E,8EAA8E;IAC9E,4DAA4D;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,WAAW,CACnB,wDAAwD;YACtD,qEAAqE;YACrE,GAAG,YAAY,4DAA4D;YAC3E,GAAG,SAAS,iCAAiC,CAChD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,WAAW,CACnB,qBAAqB,OAAO,oCAAoC;YAC9D,GAAG,YAAY,sEAAsE;YACrF,YAAY,SAAS,4DAA4D;YACjF,kFAAkF;YAClF,kCAAkC,CACrC,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,SAAS,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,MAAM,CAAC,MAAc;IAC5B,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,aAAa,CAAC,UAA4B,EAAE;IAC1D,OAAO;QACL,6EAA6E;QAC7E,2EAA2E;QAC3E,+CAA+C;QAC/C,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACpE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI;QAClD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB;IACjD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,WAAW,CACnB,yDAAyD;YACvD,6CAA6C;YAC7C,GAAG,SAAS,kEAAkE,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.connections.list()` — discovery, and nothing more.
|
|
3
|
+
*
|
|
4
|
+
* One operation in v0.1.0. It exists because without it a caller has no way to
|
|
5
|
+
* **discover** a `conn_…` id to pass to `run` (D4): the intake's surface is
|
|
6
|
+
* `run` plus the assets it needs, and an id nobody can enumerate is an id
|
|
7
|
+
* nobody can use.
|
|
8
|
+
*
|
|
9
|
+
* Everything else about connections — creating one, testing one, replacing its
|
|
10
|
+
* secret — is `outOfScope` in `endpoints.json` for this version. That is a
|
|
11
|
+
* deliberate line, not an omission: connecting an app is an interactive,
|
|
12
|
+
* secret-handling flow, and half of one in a v0.1.0 wrapper is worse than none.
|
|
13
|
+
* This namespace is therefore read-only and stays that way until the contract
|
|
14
|
+
* says otherwise.
|
|
15
|
+
*
|
|
16
|
+
* The list the server returns is a **redacted projection** — the stored secret
|
|
17
|
+
* and its refresh timestamp never leave the host — so
|
|
18
|
+
* {@linkcode ConnectionSummary} does not declare them.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
import type { HttpResponse, RequestOptions } from "./http.ts";
|
|
23
|
+
import { type ConnectionSummary } from "./types.ts";
|
|
24
|
+
/**
|
|
25
|
+
* The slice of `W6wClient` this namespace needs: the transport, and nothing
|
|
26
|
+
* else. Connections carry no `?project=` — the server scopes them by
|
|
27
|
+
* tenant/account from the credential — so, as with `vars`, this host cannot
|
|
28
|
+
* reach the client's configuration to send a scope even by accident.
|
|
29
|
+
*/
|
|
30
|
+
export interface ConnectionsHost {
|
|
31
|
+
/** Perform one request. */
|
|
32
|
+
request<T>(options: RequestOptions): Promise<HttpResponse<T>>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The `connections` namespace on a `W6wClient`.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* for (const c of await client.connections.list()) {
|
|
40
|
+
* if (c.state === "connected") console.log(c.id, c.appId);
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare class ConnectionsApi {
|
|
45
|
+
#private;
|
|
46
|
+
/**
|
|
47
|
+
* @param host - The client this namespace issues requests through.
|
|
48
|
+
*/
|
|
49
|
+
constructor(host: ConnectionsHost);
|
|
50
|
+
/**
|
|
51
|
+
* List the caller's connections.
|
|
52
|
+
*
|
|
53
|
+
* @returns The connections, unwrapped from the `connections` envelope.
|
|
54
|
+
* @throws {ApiError} On any non-2xx.
|
|
55
|
+
*/
|
|
56
|
+
list(): Promise<ConnectionSummary[]>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=connections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,KAAK,iBAAiB,EAAU,MAAM,YAAY,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAc;;IAGzB;;OAEG;gBACS,IAAI,EAAE,eAAe;IAIjC;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;CAI3C"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.connections.list()` — discovery, and nothing more.
|
|
3
|
+
*
|
|
4
|
+
* One operation in v0.1.0. It exists because without it a caller has no way to
|
|
5
|
+
* **discover** a `conn_…` id to pass to `run` (D4): the intake's surface is
|
|
6
|
+
* `run` plus the assets it needs, and an id nobody can enumerate is an id
|
|
7
|
+
* nobody can use.
|
|
8
|
+
*
|
|
9
|
+
* Everything else about connections — creating one, testing one, replacing its
|
|
10
|
+
* secret — is `outOfScope` in `endpoints.json` for this version. That is a
|
|
11
|
+
* deliberate line, not an omission: connecting an app is an interactive,
|
|
12
|
+
* secret-handling flow, and half of one in a v0.1.0 wrapper is worse than none.
|
|
13
|
+
* This namespace is therefore read-only and stays that way until the contract
|
|
14
|
+
* says otherwise.
|
|
15
|
+
*
|
|
16
|
+
* The list the server returns is a **redacted projection** — the stored secret
|
|
17
|
+
* and its refresh timestamp never leave the host — so
|
|
18
|
+
* {@linkcode ConnectionSummary} does not declare them.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
import { unwrap } from "./types.js";
|
|
23
|
+
/**
|
|
24
|
+
* The `connections` namespace on a `W6wClient`.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* for (const c of await client.connections.list()) {
|
|
29
|
+
* if (c.state === "connected") console.log(c.id, c.appId);
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class ConnectionsApi {
|
|
34
|
+
#host;
|
|
35
|
+
/**
|
|
36
|
+
* @param host - The client this namespace issues requests through.
|
|
37
|
+
*/
|
|
38
|
+
constructor(host) {
|
|
39
|
+
this.#host = host;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* List the caller's connections.
|
|
43
|
+
*
|
|
44
|
+
* @returns The connections, unwrapped from the `connections` envelope.
|
|
45
|
+
* @throws {ApiError} On any non-2xx.
|
|
46
|
+
*/
|
|
47
|
+
async list() {
|
|
48
|
+
const res = await this.#host.request({ method: "GET", path: "/connections" });
|
|
49
|
+
return unwrap(res, "connections");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAA0B,MAAM,EAAE,MAAM,YAAY,CAAC;AAa5D;;;;;;;;;GASG;AACH,MAAM,OAAO,cAAc;IAChB,KAAK,CAAkB;IAEhC;;OAEG;IACH,YAAY,IAAqB;QAC/B,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,cAAc,EAAE,CAAC,CAAC;QACvF,OAAO,MAAM,CAAsB,GAAG,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `client.documents.*` — the document store, addressed the way the server
|
|
3
|
+
* addresses it.
|
|
4
|
+
*
|
|
5
|
+
* Six operations, one HTTP call each. **Create by `key`, read by id or by key,
|
|
6
|
+
* update and delete by id** (`docs/implementation.md` §7, D6 amended by D12).
|
|
7
|
+
* There is no key-addressed façade over the id routes and no client-side
|
|
8
|
+
* list-then-filter anywhere in this file: a `getByKey` implemented as "list
|
|
9
|
+
* everything and scan" is O(n) over someone's whole store, it races, and a
|
|
10
|
+
* wrapper that has to compose two calls is describing an operation that belongs
|
|
11
|
+
* in the API.
|
|
12
|
+
*
|
|
13
|
+
* `getByKey` therefore targets a real route — `GET /documents/by-key/{key}`
|
|
14
|
+
* (verified live 2026-07-28).
|
|
15
|
+
*
|
|
16
|
+
* Documents are **project-scoped**: every route below accepts an optional
|
|
17
|
+
* `?project=`, resolved per call, then from the client's default, and otherwise
|
|
18
|
+
* left to the server (which picks the account's default project). Vars are not
|
|
19
|
+
* — see `src/vars.ts`.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import type { ResolvedConfig } from "./config.ts";
|
|
24
|
+
import { type HttpResponse, type RequestOptions } from "./http.ts";
|
|
25
|
+
import { type Doc, type DocFormat } from "./types.ts";
|
|
26
|
+
/**
|
|
27
|
+
* The slice of `W6wClient` this namespace needs: the transport, plus
|
|
28
|
+
* the resolved configuration it reads the **default project** out of. Structural
|
|
29
|
+
* rather than a concrete client type, so the namespace stays independently
|
|
30
|
+
* constructible in a test and this module never imports the client back.
|
|
31
|
+
*/
|
|
32
|
+
export interface DocumentsHost {
|
|
33
|
+
/** The resolved configuration; only `project` is read. */
|
|
34
|
+
readonly config: ResolvedConfig;
|
|
35
|
+
/** Perform one request. */
|
|
36
|
+
request<T>(options: RequestOptions): Promise<HttpResponse<T>>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Per-call options shared by every document operation.
|
|
40
|
+
*
|
|
41
|
+
* `project` overrides the client's default for this one call. Omitted
|
|
42
|
+
* everywhere, the server resolves the account's default project; an unknown id
|
|
43
|
+
* is `400 unknown_project`.
|
|
44
|
+
*/
|
|
45
|
+
export interface DocumentOptions {
|
|
46
|
+
/** Project id to scope this call to. */
|
|
47
|
+
project?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The body of `documents.create`.
|
|
51
|
+
*
|
|
52
|
+
* Addressed by `key`, because that is how the server addresses a create (D6).
|
|
53
|
+
*/
|
|
54
|
+
export interface DocumentCreateInput {
|
|
55
|
+
/** Non-empty, ≤128 characters, unique per scope + project. `409 document_exists` if taken. */
|
|
56
|
+
key: string;
|
|
57
|
+
/** Raw text; stored verbatim and never parsed. */
|
|
58
|
+
content: string;
|
|
59
|
+
/** Format hint; the server defaults it to `"text"`. */
|
|
60
|
+
format?: DocFormat;
|
|
61
|
+
/** Free text. */
|
|
62
|
+
description?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The body of `documents.update`. Every field is optional; an omitted field is
|
|
66
|
+
* left alone.
|
|
67
|
+
*
|
|
68
|
+
* **`key` is deliberately absent.** The server's PATCH body has no `key` and the
|
|
69
|
+
* key is immutable, so there is no field here to put one in — the type is what
|
|
70
|
+
* enforces it, not a comment.
|
|
71
|
+
*/
|
|
72
|
+
export interface DocumentPatch {
|
|
73
|
+
/** Replacement content. */
|
|
74
|
+
content?: string;
|
|
75
|
+
/** Replacement format hint. */
|
|
76
|
+
format?: DocFormat;
|
|
77
|
+
/** Replacement description. */
|
|
78
|
+
description?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The `documents` namespace on a `W6wClient`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const doc = await client.documents.create({ key: "welcome", content: "# Hi" });
|
|
86
|
+
* await client.documents.update(doc.id, { content: "# Hello" });
|
|
87
|
+
* await client.documents.delete(doc.id);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare class DocumentsApi {
|
|
91
|
+
#private;
|
|
92
|
+
/**
|
|
93
|
+
* @param host - The client this namespace issues requests through.
|
|
94
|
+
*/
|
|
95
|
+
constructor(host: DocumentsHost);
|
|
96
|
+
/**
|
|
97
|
+
* List the caller's documents.
|
|
98
|
+
*
|
|
99
|
+
* @param options - Optional per-call project scope.
|
|
100
|
+
* @returns The documents, unwrapped from the `documents` envelope.
|
|
101
|
+
* @throws {ApiError} On any non-2xx, e.g. `400 unknown_project`.
|
|
102
|
+
*/
|
|
103
|
+
list(options?: DocumentOptions): Promise<Doc[]>;
|
|
104
|
+
/**
|
|
105
|
+
* Fetch one document by its server-issued id.
|
|
106
|
+
*
|
|
107
|
+
* @param id - The `doc_…` id.
|
|
108
|
+
* @param options - Optional per-call project scope.
|
|
109
|
+
* @returns The document.
|
|
110
|
+
* @throws {ApiError} `404 unknown_document` when there is no such id.
|
|
111
|
+
*/
|
|
112
|
+
get(id: string, options?: DocumentOptions): Promise<Doc>;
|
|
113
|
+
/**
|
|
114
|
+
* Fetch one document by the `key` its author chose.
|
|
115
|
+
*
|
|
116
|
+
* The key is percent-encoded at interpolation by the `path` tag, which is not
|
|
117
|
+
* ceremony: the server accepts any non-empty key up to 128 characters, so
|
|
118
|
+
* `"a/b"` and `".."` are keys a user can legitimately create, and concatenated
|
|
119
|
+
* naively they address a *different route* — `".."` resolves to the list
|
|
120
|
+
* endpoint and returns every document with a `200` and no error anywhere.
|
|
121
|
+
*
|
|
122
|
+
* Encoding, never validation: a key the server accepts is sent as-is
|
|
123
|
+
* (encoded). This method does not reject, trim or canonicalise a key —
|
|
124
|
+
* refusing one locally would make a document that exists permanently
|
|
125
|
+
* unreadable through this client.
|
|
126
|
+
*
|
|
127
|
+
* @param key - The document key, sent encoded and otherwise untouched.
|
|
128
|
+
* @param options - Optional per-call project scope.
|
|
129
|
+
* @returns The document.
|
|
130
|
+
* @throws {ApiError} `404 unknown_document` when there is no such key.
|
|
131
|
+
*/
|
|
132
|
+
getByKey(key: string, options?: DocumentOptions): Promise<Doc>;
|
|
133
|
+
/**
|
|
134
|
+
* Create a document under a caller-chosen key.
|
|
135
|
+
*
|
|
136
|
+
* @param input - `key` and `content` are required; `format` defaults server-side to `"text"`.
|
|
137
|
+
* @param options - Optional per-call project scope.
|
|
138
|
+
* @returns The created document (the server answers `201`).
|
|
139
|
+
* @throws {ApiError} `409 document_exists` on a duplicate key — the code reaches the caller intact.
|
|
140
|
+
*/
|
|
141
|
+
create(input: DocumentCreateInput, options?: DocumentOptions): Promise<Doc>;
|
|
142
|
+
/**
|
|
143
|
+
* Patch a document's content, format or description.
|
|
144
|
+
*
|
|
145
|
+
* Addressed by id, never by key, and the key itself cannot be changed.
|
|
146
|
+
*
|
|
147
|
+
* @param id - The `doc_…` id.
|
|
148
|
+
* @param patch - The fields to change; omitted fields are left alone.
|
|
149
|
+
* @param options - Optional per-call project scope.
|
|
150
|
+
* @returns The updated document.
|
|
151
|
+
* @throws {ApiError} `404 unknown_document` when there is no such id.
|
|
152
|
+
*/
|
|
153
|
+
update(id: string, patch: DocumentPatch, options?: DocumentOptions): Promise<Doc>;
|
|
154
|
+
/**
|
|
155
|
+
* Delete a document.
|
|
156
|
+
*
|
|
157
|
+
* Returns nothing: the server's `{ok: true}` carries no information a caller
|
|
158
|
+
* can use, and unwrapping it to a value would invite `if (await delete(...))`.
|
|
159
|
+
* Deleting an unknown id is `404 unknown_document`, **not** a silent success —
|
|
160
|
+
* the delete is not idempotent and this method does not pretend otherwise.
|
|
161
|
+
*
|
|
162
|
+
* @param id - The `doc_…` id.
|
|
163
|
+
* @param options - Optional per-call project scope.
|
|
164
|
+
* @throws {ApiError} `404 unknown_document` when there is no such id.
|
|
165
|
+
*/
|
|
166
|
+
delete(id: string, options?: DocumentOptions): Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/documents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,YAAY,EAAQ,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAU,MAAM,YAAY,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,2BAA2B;IAC3B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAY;;IAGvB;;OAEG;gBACS,IAAI,EAAE,aAAa;IAa/B;;;;;;OAMG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IASrD;;;;;;;OAOG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IAS9D;;;;;;;;;;;;;;;;;;OAkBG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IASpE;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IAkBjF;;;;;;;;;;OAUG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IAcvF;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAOnE"}
|