@every-app/sdk 0.3.0-rc.2 → 0.3.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/sentinel.d.ts +57 -2
- package/dist/cloudflare/sentinel.d.ts.map +1 -1
- package/dist/cloudflare/sentinel.js +27 -2
- package/dist/cloudflare/worker.d.ts +297 -5
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +279 -12
- package/dist/dev/index.d.ts +1 -1
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +1 -1
- package/dist/dev/keypair.d.ts +2 -0
- package/dist/dev/keypair.d.ts.map +1 -1
- package/dist/dev/keypair.js +2 -0
- package/dist/internal/aiDefault.d.ts +141 -0
- package/dist/internal/aiDefault.d.ts.map +1 -0
- package/dist/internal/aiDefault.js +204 -0
- package/dist/internal/aiProviders.d.ts +4 -1
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +5 -1
- package/dist/internal/appSettings.d.ts +20 -2
- package/dist/internal/appSettings.d.ts.map +1 -1
- package/dist/internal/appSettings.js +53 -7
- package/dist/internal/audit.d.ts +108 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +235 -0
- package/dist/internal/capabilities.d.ts +276 -7
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +111 -0
- package/dist/internal/catalog/index.d.ts +39 -2
- package/dist/internal/catalog/index.d.ts.map +1 -1
- package/dist/internal/catalog/inference.d.ts +39 -2
- package/dist/internal/catalog/inference.d.ts.map +1 -1
- package/dist/internal/catalog/inference.js +36 -4
- package/dist/internal/devProviders.d.ts +2 -2
- package/dist/internal/devProviders.d.ts.map +1 -1
- package/dist/internal/devProviders.js +19 -1
- package/dist/internal/events.d.ts +13 -2
- package/dist/internal/events.d.ts.map +1 -1
- package/dist/internal/events.js +42 -4
- package/dist/internal/identity.d.ts +29 -3
- package/dist/internal/identity.d.ts.map +1 -1
- package/dist/internal/identity.js +37 -9
- package/dist/internal/index.d.ts +5 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -1
- package/dist/internal/members.d.ts +3 -2
- package/dist/internal/members.d.ts.map +1 -1
- package/dist/internal/oauthPresets.d.ts +29 -0
- package/dist/internal/oauthPresets.d.ts.map +1 -0
- package/dist/internal/oauthPresets.js +534 -0
- package/dist/internal/oauthScopes.d.ts +56 -1
- package/dist/internal/oauthScopes.d.ts.map +1 -1
- package/dist/internal/oauthScopes.js +98 -4
- package/dist/internal/oauthSpec.d.ts +59 -0
- package/dist/internal/oauthSpec.d.ts.map +1 -0
- package/dist/internal/oauthSpec.js +676 -0
- package/dist/internal/protocol.d.ts +36 -1
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +30 -1
- package/dist/internal/providerRegistry.d.ts +17 -6
- package/dist/internal/providerRegistry.d.ts.map +1 -1
- package/dist/internal/providerRegistry.js +47 -2
- package/dist/internal/providerSpec.d.ts +11 -7
- package/dist/internal/providerSpec.d.ts.map +1 -1
- package/dist/internal/providerSpec.js +134 -37
- package/dist/internal/signInProviders.d.ts.map +1 -1
- package/dist/internal/signInProviders.js +11 -4
- package/dist/server/ai.d.ts +45 -0
- package/dist/server/ai.d.ts.map +1 -0
- package/dist/server/ai.js +40 -0
- package/dist/server/attribution.d.ts +9 -5
- package/dist/server/attribution.d.ts.map +1 -1
- package/dist/server/attribution.js +12 -4
- package/dist/server/connectUrl.d.ts +21 -0
- package/dist/server/connectUrl.d.ts.map +1 -0
- package/dist/server/connectUrl.js +37 -0
- package/dist/server/context.d.ts +68 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +117 -0
- package/dist/server/emit.d.ts +1 -1
- package/dist/server/emit.d.ts.map +1 -1
- package/dist/server/emit.js +4 -4
- package/dist/server/everyApp.d.ts +27 -7
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +106 -5
- package/dist/server/fromMcpTools.d.ts +89 -0
- package/dist/server/fromMcpTools.d.ts.map +1 -0
- package/dist/server/fromMcpTools.js +192 -0
- package/dist/server/gatewayFetch.d.ts +8 -6
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +78 -11
- package/dist/server/index.d.ts +7 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +6 -2
- package/dist/server/integrationFetch.d.ts +55 -8
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +198 -18
- package/dist/server/listMembers.d.ts +1 -1
- package/dist/server/listMembers.d.ts.map +1 -1
- package/dist/server/listMembers.js +5 -8
- package/dist/server/sendEmail.d.ts +1 -1
- package/dist/server/sendEmail.d.ts.map +1 -1
- package/dist/server/sendEmail.js +4 -4
- package/dist/server/toolsEndpoint.d.ts.map +1 -1
- package/dist/server/toolsEndpoint.js +11 -5
- package/package.json +13 -14
- package/LICENSE +0 -21
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ai()`: the Gateway's default chat model for an app that needs "a model"
|
|
3
|
+
* rather than one provider (docs/design/2026-10-model-providers.md). The
|
|
4
|
+
* manifest says `ai: { chat: true }` (or `{ chat: { why } }`); the Gateway's
|
|
5
|
+
* operator decides which provider and model that is (`everyapp ai
|
|
6
|
+
* default`, else OpenRouter → Workers AI → OpenAI → …, the first with its
|
|
7
|
+
* key set), and the app never names either: it sends OpenAI-shaped chat
|
|
8
|
+
* completions (and embeddings) to `/api/ai/default/v1/…` with `model:
|
|
9
|
+
* "default"` or no model at all, and the Gateway fills the model in.
|
|
10
|
+
*
|
|
11
|
+
* An OpenAI client takes `baseURL` and `fetch` as they are:
|
|
12
|
+
*
|
|
13
|
+
* const { baseURL, fetch, model } = ai({ env, for: request });
|
|
14
|
+
* const client = new OpenAI({ baseURL, fetch, apiKey: "gateway-managed" });
|
|
15
|
+
* await client.chat.completions.create({ model, messages });
|
|
16
|
+
*
|
|
17
|
+
* In local development with no Gateway, the developer's own key in
|
|
18
|
+
* `.dev.vars` decides the provider by the same order (createGatewayFetch's
|
|
19
|
+
* fallback). An app that needs one provider in particular keeps listing it
|
|
20
|
+
* under `providers` and calling `/api/ai/<provider>/…`.
|
|
21
|
+
*/
|
|
22
|
+
import { AI_DEFAULT_MODEL } from "../internal/index.js";
|
|
23
|
+
import { type CreateGatewayFetchOptions } from "./gatewayFetch.js";
|
|
24
|
+
export interface AiClient {
|
|
25
|
+
/** `http://every-app-gateway.internal/api/ai/default/v1`: an OpenAI client's base URL. */
|
|
26
|
+
baseURL: string;
|
|
27
|
+
/** The fetch that reaches the Gateway (or, in dev, the provider directly). */
|
|
28
|
+
fetch: typeof fetch;
|
|
29
|
+
/** The model name that means "whatever the Gateway's default is": `default`. */
|
|
30
|
+
model: typeof AI_DEFAULT_MODEL;
|
|
31
|
+
/** The default route's chat completions URL, for a plain `fetch`. */
|
|
32
|
+
chatCompletionsUrl: string;
|
|
33
|
+
/** The default route's embeddings URL, for a plain `fetch`. */
|
|
34
|
+
embeddingsUrl: string;
|
|
35
|
+
}
|
|
36
|
+
/** The base URL of the default route, as the SDK and the docs name it. */
|
|
37
|
+
export declare const AI_DEFAULT_BASE_URL = "http://every-app-gateway.internal/api/ai/default/v1";
|
|
38
|
+
/**
|
|
39
|
+
* The Gateway's default chat model as a client: a base URL, a fetch and
|
|
40
|
+
* the model name to send. Throws `ConfigurationError` where
|
|
41
|
+
* `createGatewayFetch` does (no binding and no dev key) and
|
|
42
|
+
* `AttributionError` where a shared app's call says nobody's.
|
|
43
|
+
*/
|
|
44
|
+
export declare function ai(options: CreateGatewayFetchOptions): AiClient;
|
|
45
|
+
//# sourceMappingURL=ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/server/ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,gBAAgB,EAAuB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,QAAQ;IACvB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,gFAAgF;IAChF,KAAK,EAAE,OAAO,gBAAgB,CAAC;IAC/B,qEAAqE;IACrE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,wDAAuD,CAAC;AAExF;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,OAAO,EAAE,yBAAyB,GAAG,QAAQ,CAQ/D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ai()`: the Gateway's default chat model for an app that needs "a model"
|
|
3
|
+
* rather than one provider (docs/design/2026-10-model-providers.md). The
|
|
4
|
+
* manifest says `ai: { chat: true }` (or `{ chat: { why } }`); the Gateway's
|
|
5
|
+
* operator decides which provider and model that is (`everyapp ai
|
|
6
|
+
* default`, else OpenRouter → Workers AI → OpenAI → …, the first with its
|
|
7
|
+
* key set), and the app never names either: it sends OpenAI-shaped chat
|
|
8
|
+
* completions (and embeddings) to `/api/ai/default/v1/…` with `model:
|
|
9
|
+
* "default"` or no model at all, and the Gateway fills the model in.
|
|
10
|
+
*
|
|
11
|
+
* An OpenAI client takes `baseURL` and `fetch` as they are:
|
|
12
|
+
*
|
|
13
|
+
* const { baseURL, fetch, model } = ai({ env, for: request });
|
|
14
|
+
* const client = new OpenAI({ baseURL, fetch, apiKey: "gateway-managed" });
|
|
15
|
+
* await client.chat.completions.create({ model, messages });
|
|
16
|
+
*
|
|
17
|
+
* In local development with no Gateway, the developer's own key in
|
|
18
|
+
* `.dev.vars` decides the provider by the same order (createGatewayFetch's
|
|
19
|
+
* fallback). An app that needs one provider in particular keeps listing it
|
|
20
|
+
* under `providers` and calling `/api/ai/<provider>/…`.
|
|
21
|
+
*/
|
|
22
|
+
import { AI_DEFAULT_MODEL, AI_DEFAULT_PROVIDER } from "../internal/index.js";
|
|
23
|
+
import { BINDING_ORIGIN, createGatewayFetch, } from "./gatewayFetch.js";
|
|
24
|
+
/** The base URL of the default route, as the SDK and the docs name it. */
|
|
25
|
+
export const AI_DEFAULT_BASE_URL = `${BINDING_ORIGIN}/api/ai/${AI_DEFAULT_PROVIDER}/v1`;
|
|
26
|
+
/**
|
|
27
|
+
* The Gateway's default chat model as a client: a base URL, a fetch and
|
|
28
|
+
* the model name to send. Throws `ConfigurationError` where
|
|
29
|
+
* `createGatewayFetch` does (no binding and no dev key) and
|
|
30
|
+
* `AttributionError` where a shared app's call says nobody's.
|
|
31
|
+
*/
|
|
32
|
+
export function ai(options) {
|
|
33
|
+
return {
|
|
34
|
+
baseURL: AI_DEFAULT_BASE_URL,
|
|
35
|
+
fetch: createGatewayFetch(options),
|
|
36
|
+
model: AI_DEFAULT_MODEL,
|
|
37
|
+
chatCompletionsUrl: `${AI_DEFAULT_BASE_URL}/chat/completions`,
|
|
38
|
+
embeddingsUrl: `${AI_DEFAULT_BASE_URL}/embeddings`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Whom a call through the gateway is for, which decides the organization
|
|
3
|
-
* it counts against:
|
|
3
|
+
* it counts against. Left out, it comes from the request context: the
|
|
4
|
+
* request `everyApp()` is serving (its person, while the identity is good),
|
|
5
|
+
* or the organization `withOrganization()` named. Given explicitly:
|
|
4
6
|
*
|
|
5
7
|
* - the inbound `Request`: its person, by the identity the gateway put on
|
|
6
8
|
* it (forwarded as is);
|
|
@@ -24,11 +26,13 @@ export declare class AttributionError extends Error {
|
|
|
24
26
|
constructor(message: string);
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
29
|
+
* Whom the call is for, checked before any call is made: `target` as the
|
|
30
|
+
* app passed it, else the request context's answer
|
|
31
|
+
* ({@link attributionFromContext}; a `RequestContextError` outside every
|
|
32
|
+
* context). A shared app's Worker must end up with the request or an
|
|
33
|
+
* organization, and anything passed must be one of the two shapes.
|
|
30
34
|
*/
|
|
31
|
-
export declare function
|
|
35
|
+
export declare function attributionFor(env: object, target: GatewayCallFor | undefined, what: string): GatewayCallFor | undefined;
|
|
32
36
|
/**
|
|
33
37
|
* Put the call's attribution on its headers: the request's identity, or the
|
|
34
38
|
* background work's organization, and never one the app set itself.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/server/attribution.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/server/attribution.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GACtB,OAAO,GACP;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,0BAA0B;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,GACX,cAAc,GAAG,SAAS,CAI5B;AA8BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,cAAc,GAAG,SAAS,GACjC,IAAI,CAUN;AASD,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAO1D"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IDENTITY_HEADER, ORG_HEADER, SHARED_ENV } from "../internal/index.js";
|
|
2
|
+
import { attributionFromContext } from "./context.js";
|
|
2
3
|
/**
|
|
3
4
|
* A gateway call that doesn't say whom it is for where it must: from a
|
|
4
5
|
* shared app's Worker, with neither the request nor an organization.
|
|
@@ -11,11 +12,18 @@ export class AttributionError extends Error {
|
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Whom the call is for, checked before any call is made: `target` as the
|
|
16
|
+
* app passed it, else the request context's answer
|
|
17
|
+
* ({@link attributionFromContext}; a `RequestContextError` outside every
|
|
18
|
+
* context). A shared app's Worker must end up with the request or an
|
|
19
|
+
* organization, and anything passed must be one of the two shapes.
|
|
17
20
|
*/
|
|
18
|
-
export function
|
|
21
|
+
export function attributionFor(env, target, what) {
|
|
22
|
+
const resolved = target === undefined ? attributionFromContext(what) : target;
|
|
23
|
+
checkAttribution(env, resolved, what);
|
|
24
|
+
return resolved;
|
|
25
|
+
}
|
|
26
|
+
function checkAttribution(env, target, what) {
|
|
19
27
|
if (target !== undefined && !isRequest(target)) {
|
|
20
28
|
if (target === null || typeof target !== "object" || !target.background) {
|
|
21
29
|
throw new AttributionError(`${what}: \`for\` is the inbound Request or { background: true, organizationId }.`);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ConnectionAccount } from "../internal/index.js";
|
|
2
|
+
export interface ConnectUrlOptions {
|
|
3
|
+
/** The Worker env: `GATEWAY_URL`, which every deployed Worker and `everyapp dev` set. */
|
|
4
|
+
env: object;
|
|
5
|
+
/** The OAuth provider's id (`google-workspace`, `github`). */
|
|
6
|
+
provider: string;
|
|
7
|
+
/**
|
|
8
|
+
* Where to send the person afterwards: the app's own URL (absolute) or
|
|
9
|
+
* a path on the Gateway. Absent: Settings → Connected accounts.
|
|
10
|
+
*/
|
|
11
|
+
returnTo?: string;
|
|
12
|
+
/** Whose connection to make: the person's (default) or the organization's (owner or admin). */
|
|
13
|
+
account?: ConnectionAccount;
|
|
14
|
+
/** Scope sets to ask for; absent: the union every active app that lists the provider declares. */
|
|
15
|
+
sets?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
/** The path of the connect page for `provider` on the Gateway. */
|
|
18
|
+
export declare function connectPath(provider: string): string;
|
|
19
|
+
/** The absolute URL that starts the Gateway-owned flow for `provider`. */
|
|
20
|
+
export declare function connectUrl({ env, provider, returnTo, account, sets, }: ConnectUrlOptions): string;
|
|
21
|
+
//# sourceMappingURL=connectUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectUrl.d.ts","sourceRoot":"","sources":["../../src/server/connectUrl.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,kGAAkG;IAClG,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,IAAI,GACL,EAAE,iBAAiB,GAAG,MAAM,CAmB5B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app sends a person to connect an OAuth provider the Gateway
|
|
3
|
+
* runs the flow for (docs/design/2026-10-oauth-providers.md section 5):
|
|
4
|
+
* `<gateway>/connect/<id>?return=<back here>&account=<user|organization>`.
|
|
5
|
+
* The Gateway checks the session, asks the provider for the union of the
|
|
6
|
+
* sets every active app declares, finishes on its own callback and sends
|
|
7
|
+
* the browser back to `returnTo`, which must be a path on the Gateway or
|
|
8
|
+
* an https URL on one of its app hosts (in local dev also localhost).
|
|
9
|
+
*/
|
|
10
|
+
import { ConfigurationError } from "../internal/index.js";
|
|
11
|
+
/** The path of the connect page for `provider` on the Gateway. */
|
|
12
|
+
export function connectPath(provider) {
|
|
13
|
+
return `/connect/${encodeURIComponent(provider)}`;
|
|
14
|
+
}
|
|
15
|
+
/** The absolute URL that starts the Gateway-owned flow for `provider`. */
|
|
16
|
+
export function connectUrl({ env, provider, returnTo, account, sets, }) {
|
|
17
|
+
const values = env;
|
|
18
|
+
const gateway = values["GATEWAY_URL"];
|
|
19
|
+
if (typeof gateway !== "string" || !gateway.trim()) {
|
|
20
|
+
throw new ConfigurationError("connectUrl() needs GATEWAY_URL in the Worker env: the deploy sets it, and everyapp dev sets it to the local gateway.");
|
|
21
|
+
}
|
|
22
|
+
let base;
|
|
23
|
+
try {
|
|
24
|
+
base = new URL(gateway.trim());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new ConfigurationError(`GATEWAY_URL isn't a URL: ${gateway}`);
|
|
28
|
+
}
|
|
29
|
+
const url = new URL(connectPath(provider), base.origin);
|
|
30
|
+
if (returnTo)
|
|
31
|
+
url.searchParams.set("return", returnTo);
|
|
32
|
+
if (account)
|
|
33
|
+
url.searchParams.set("account", account);
|
|
34
|
+
if (sets && sets.length > 0)
|
|
35
|
+
url.searchParams.set("sets", sets.join(","));
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { EveryAppUser } from "../internal/index.js";
|
|
2
|
+
/** What `everyApp()` keeps while it serves one request. */
|
|
3
|
+
export interface ServedRequest {
|
|
4
|
+
request: Request;
|
|
5
|
+
/** The verified user, or null on a public route. */
|
|
6
|
+
user: EveryAppUser | null;
|
|
7
|
+
/** When the forwarded identity expires (epoch ms); null without one. */
|
|
8
|
+
expiresAt: number | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A forwarded identity lives 120 seconds. One this close to its expiry could
|
|
12
|
+
* expire before the Gateway checks it (a 401 the call can't recover from),
|
|
13
|
+
* so work still running then goes on as the organization's background work.
|
|
14
|
+
*/
|
|
15
|
+
export declare const IDENTITY_EXPIRY_MARGIN_MS = 15000;
|
|
16
|
+
/**
|
|
17
|
+
* Code `request_context_missing`: `currentUser()` or a Gateway call with
|
|
18
|
+
* no `for`, outside any request `everyApp()` serves and outside
|
|
19
|
+
* `withOrganization()`. Work no request started names its organization.
|
|
20
|
+
*/
|
|
21
|
+
export declare class RequestContextError extends Error {
|
|
22
|
+
readonly code = "request_context_missing";
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Code `attribution_organization_mismatch`: `withOrganization()` named
|
|
27
|
+
* another organization than the request being served belongs to.
|
|
28
|
+
*/
|
|
29
|
+
export declare class OrganizationMismatchError extends Error {
|
|
30
|
+
readonly code = "attribution_organization_mismatch";
|
|
31
|
+
constructor(message: string);
|
|
32
|
+
}
|
|
33
|
+
/** Serve `fn` for one request: `everyApp()` calls this; apps don't. */
|
|
34
|
+
export declare function serveRequest<T>(served: ServedRequest, fn: () => T): T;
|
|
35
|
+
/**
|
|
36
|
+
* Run `fn` as `organizationId`'s background work: every Gateway call made
|
|
37
|
+
* inside it (and in what it awaits or schedules) is that organization's,
|
|
38
|
+
* with no person behind it. For a Workflow step, a cron, a queue consumer or
|
|
39
|
+
* a Durable Object alarm, which no request started. An organization's own
|
|
40
|
+
* app names its own (`env.EVERY_APP_ORG_ID`); a shared app's Worker names
|
|
41
|
+
* the one the work is for. Inside a request another organization's person
|
|
42
|
+
* is driving, it throws {@link OrganizationMismatchError}; inside that
|
|
43
|
+
* organization's own request, the person stays attributed while their
|
|
44
|
+
* identity is good.
|
|
45
|
+
*/
|
|
46
|
+
export declare function withOrganization<T>(organizationId: string, fn: () => T): T;
|
|
47
|
+
/**
|
|
48
|
+
* The verified user of the request being served: an `EveryAppUser`, or
|
|
49
|
+
* `null` on a public route and inside `withOrganization()`'s background
|
|
50
|
+
* work. Throws {@link RequestContextError} outside both: there is no one
|
|
51
|
+
* to be, and a handler that isn't under `everyApp()` is a bug.
|
|
52
|
+
*/
|
|
53
|
+
export declare function currentUser(): EveryAppUser | null;
|
|
54
|
+
/**
|
|
55
|
+
* Whom a Gateway call made now is for, from the context:
|
|
56
|
+
*
|
|
57
|
+
* - the request being served, while its identity is good;
|
|
58
|
+
* - else that organization's background work (the identity is about to
|
|
59
|
+
* expire, or `withOrganization()` named it);
|
|
60
|
+
* - `undefined` on a public route of an organization's own app, which the
|
|
61
|
+
* Gateway attributes to the app's organization; and
|
|
62
|
+
* - a {@link RequestContextError} outside every context.
|
|
63
|
+
*/
|
|
64
|
+
export declare function attributionFromContext(what: string, now?: number): Request | {
|
|
65
|
+
background: true;
|
|
66
|
+
organizationId?: string;
|
|
67
|
+
} | undefined;
|
|
68
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,wEAAwE;IACxE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAUD;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,6BAA6B;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,uCAAuC;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAErE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAc1E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,YAAY,GAAG,IAAI,CAQjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAmB,GACvB,OAAO,GAAG;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAoBrE"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request context: whom the app is serving, kept for the whole of a
|
|
3
|
+
* request's work (every `await`, `ctx.waitUntil()`, a streaming body) in an
|
|
4
|
+
* `AsyncLocalStorage`, which every Every App Worker has (`nodejs_compat`).
|
|
5
|
+
*
|
|
6
|
+
* `everyApp()` opens it around the handler and around each tool call, with
|
|
7
|
+
* the verified user and the request the Gateway forwarded. Deeper in the
|
|
8
|
+
* app, `currentUser()` reads the user without the request, and every call
|
|
9
|
+
* back to the Gateway (`integrationFetch`, `ai`, `sendEmail`, `emit`, ...)
|
|
10
|
+
* is attributed to that person without a `for`.
|
|
11
|
+
*
|
|
12
|
+
* Work no request started (a cron, a Workflow step, a queue consumer, a
|
|
13
|
+
* Durable Object alarm) has no context of its own: it runs under
|
|
14
|
+
* `withOrganization(organizationId, fn)`, which makes every Gateway call
|
|
15
|
+
* inside it that organization's background work. A Gateway call with
|
|
16
|
+
* neither is refused before it is made ({@link RequestContextError}): the
|
|
17
|
+
* SDK never acts as nobody.
|
|
18
|
+
*/
|
|
19
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
20
|
+
const scopes = new AsyncLocalStorage();
|
|
21
|
+
/**
|
|
22
|
+
* A forwarded identity lives 120 seconds. One this close to its expiry could
|
|
23
|
+
* expire before the Gateway checks it (a 401 the call can't recover from),
|
|
24
|
+
* so work still running then goes on as the organization's background work.
|
|
25
|
+
*/
|
|
26
|
+
export const IDENTITY_EXPIRY_MARGIN_MS = 15_000;
|
|
27
|
+
/**
|
|
28
|
+
* Code `request_context_missing`: `currentUser()` or a Gateway call with
|
|
29
|
+
* no `for`, outside any request `everyApp()` serves and outside
|
|
30
|
+
* `withOrganization()`. Work no request started names its organization.
|
|
31
|
+
*/
|
|
32
|
+
export class RequestContextError extends Error {
|
|
33
|
+
code = "request_context_missing";
|
|
34
|
+
constructor(message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = "RequestContextError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Code `attribution_organization_mismatch`: `withOrganization()` named
|
|
41
|
+
* another organization than the request being served belongs to.
|
|
42
|
+
*/
|
|
43
|
+
export class OrganizationMismatchError extends Error {
|
|
44
|
+
code = "attribution_organization_mismatch";
|
|
45
|
+
constructor(message) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = "OrganizationMismatchError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Serve `fn` for one request: `everyApp()` calls this; apps don't. */
|
|
51
|
+
export function serveRequest(served, fn) {
|
|
52
|
+
return scopes.run({ served }, fn);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Run `fn` as `organizationId`'s background work: every Gateway call made
|
|
56
|
+
* inside it (and in what it awaits or schedules) is that organization's,
|
|
57
|
+
* with no person behind it. For a Workflow step, a cron, a queue consumer or
|
|
58
|
+
* a Durable Object alarm, which no request started. An organization's own
|
|
59
|
+
* app names its own (`env.EVERY_APP_ORG_ID`); a shared app's Worker names
|
|
60
|
+
* the one the work is for. Inside a request another organization's person
|
|
61
|
+
* is driving, it throws {@link OrganizationMismatchError}; inside that
|
|
62
|
+
* organization's own request, the person stays attributed while their
|
|
63
|
+
* identity is good.
|
|
64
|
+
*/
|
|
65
|
+
export function withOrganization(organizationId, fn) {
|
|
66
|
+
if (typeof organizationId !== "string" || organizationId.trim() === "") {
|
|
67
|
+
throw new TypeError("withOrganization(organizationId, fn) needs a non-empty organization id (an organization's own app passes env.EVERY_APP_ORG_ID).");
|
|
68
|
+
}
|
|
69
|
+
const parent = scopes.getStore();
|
|
70
|
+
const served = parent?.served;
|
|
71
|
+
if (served?.user && served.user.orgId !== organizationId) {
|
|
72
|
+
throw new OrganizationMismatchError(`withOrganization("${organizationId}") was called while serving a request of organization "${served.user.orgId}".`);
|
|
73
|
+
}
|
|
74
|
+
return scopes.run({ ...parent, organizationId }, fn);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The verified user of the request being served: an `EveryAppUser`, or
|
|
78
|
+
* `null` on a public route and inside `withOrganization()`'s background
|
|
79
|
+
* work. Throws {@link RequestContextError} outside both: there is no one
|
|
80
|
+
* to be, and a handler that isn't under `everyApp()` is a bug.
|
|
81
|
+
*/
|
|
82
|
+
export function currentUser() {
|
|
83
|
+
const scope = scopes.getStore();
|
|
84
|
+
if (!scope) {
|
|
85
|
+
throw new RequestContextError("currentUser() was called outside a request everyApp() serves and outside withOrganization(): there is no user here.");
|
|
86
|
+
}
|
|
87
|
+
return scope.served?.user ?? null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Whom a Gateway call made now is for, from the context:
|
|
91
|
+
*
|
|
92
|
+
* - the request being served, while its identity is good;
|
|
93
|
+
* - else that organization's background work (the identity is about to
|
|
94
|
+
* expire, or `withOrganization()` named it);
|
|
95
|
+
* - `undefined` on a public route of an organization's own app, which the
|
|
96
|
+
* Gateway attributes to the app's organization; and
|
|
97
|
+
* - a {@link RequestContextError} outside every context.
|
|
98
|
+
*/
|
|
99
|
+
export function attributionFromContext(what, now = Date.now()) {
|
|
100
|
+
const scope = scopes.getStore();
|
|
101
|
+
if (!scope) {
|
|
102
|
+
throw new RequestContextError(`${what} was called with no \`for\`, outside a request everyApp() serves and outside withOrganization(): the call would be nobody's. Pass for: request, or run the work under withOrganization(organizationId, fn).`);
|
|
103
|
+
}
|
|
104
|
+
const served = scope.served;
|
|
105
|
+
if (served?.user) {
|
|
106
|
+
const fresh = served.expiresAt === null ||
|
|
107
|
+
now < served.expiresAt - IDENTITY_EXPIRY_MARGIN_MS;
|
|
108
|
+
// withOrganization() refused any other organization than the request's.
|
|
109
|
+
if (fresh)
|
|
110
|
+
return served.request;
|
|
111
|
+
return { background: true, organizationId: served.user.orgId };
|
|
112
|
+
}
|
|
113
|
+
if (scope.organizationId) {
|
|
114
|
+
return { background: true, organizationId: scope.organizationId };
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
package/dist/server/emit.d.ts
CHANGED
|
@@ -59,5 +59,5 @@ export interface EmitOptions {
|
|
|
59
59
|
* the gateway checks it, printed, and answered `{ id: "dev-…", type }`;
|
|
60
60
|
* nothing is delivered.
|
|
61
61
|
*/
|
|
62
|
-
export declare function emit({ env, for:
|
|
62
|
+
export declare function emit({ env, for: explicitTarget, event, data, }: EmitOptions): Promise<EmitEventResult>;
|
|
63
63
|
//# sourceMappingURL=emit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/server/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EASL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,WAAW;IAC1B,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,IAAI,CAAC,EACzB,GAAG,EACH,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/server/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EASL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,WAAW;IAC1B,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,IAAI,CAAC,EACzB,GAAG,EACH,GAAG,EAAE,cAAc,EACnB,KAAK,EACL,IAAI,GACL,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAoBxC"}
|
package/dist/server/emit.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* two can't drift.
|
|
10
10
|
*/
|
|
11
11
|
import { APP_EVENT_DATA_MAX_BYTES, APP_ID_ENV, ConfigurationError, EVENTS_EMIT_PATH, appEventNameProblem, appEventType, checkEventData, } from "../internal/index.js";
|
|
12
|
-
import { applyAttribution,
|
|
12
|
+
import { applyAttribution, attributionFor, } from "./attribution.js";
|
|
13
13
|
import { BINDING_ORIGIN } from "./gatewayFetch.js";
|
|
14
14
|
import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
|
|
15
15
|
/**
|
|
@@ -36,8 +36,8 @@ import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
|
|
|
36
36
|
* the gateway checks it, printed, and answered `{ id: "dev-…", type }`;
|
|
37
37
|
* nothing is delivered.
|
|
38
38
|
*/
|
|
39
|
-
export async function emit({ env, for:
|
|
40
|
-
|
|
39
|
+
export async function emit({ env, for: explicitTarget, event, data, }) {
|
|
40
|
+
const target = attributionFor(env, explicitTarget, "emit");
|
|
41
41
|
const values = env;
|
|
42
42
|
const binding = values["EVERY_APP_GATEWAY"];
|
|
43
43
|
if (binding) {
|
|
@@ -66,7 +66,7 @@ async function emitThroughGateway(binding, target, body) {
|
|
|
66
66
|
throw new GatewayRefusalError({
|
|
67
67
|
status: response.status,
|
|
68
68
|
code: "event_emit_failed",
|
|
69
|
-
message: `The
|
|
69
|
+
message: `The EveryApp gateway answered ${response.status} to the event.`,
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
return (await response.json());
|
|
@@ -14,11 +14,21 @@
|
|
|
14
14
|
* `cloudflare.config.ts` imports from the Worker in dev).
|
|
15
15
|
* It also answers the gateway's internal tools contract
|
|
16
16
|
* (`/__everyapp/tools/*`) for the app's `defineTools()` catalog.
|
|
17
|
+
*
|
|
18
|
+
* Around the handler and around each tool call it opens the request
|
|
19
|
+
* context (context.ts): `currentUser()` reads the user anywhere below, and
|
|
20
|
+
* every call back to the Gateway is attributed to the request without a
|
|
21
|
+
* `for`. A deployed Worker is pinned to its organization
|
|
22
|
+
* (`EVERY_APP_ORG_ID`), and an identity for any other is refused on both
|
|
23
|
+
* paths. The response leaves without `Set-Cookie`: the perimeter strips
|
|
24
|
+
* every `Cookie` before a request reaches the app, so a cookie the app's
|
|
25
|
+
* framework sets could never come back, and one named like the Gateway's
|
|
26
|
+
* session cookie would lock the person out of the app host.
|
|
17
27
|
*/
|
|
18
|
-
import { ConfigurationError, IdentityError, type EveryAppUser, type IdentityResult } from "../internal/index.js";
|
|
28
|
+
import { ConfigurationError, IdentityError, isAdmin, type EveryAppUser, type IdentityResult, type OrgRole } from "../internal/index.js";
|
|
19
29
|
import type { ToolSet } from "./tools.js";
|
|
20
|
-
export { ConfigurationError, IdentityError };
|
|
21
|
-
export type { EveryAppUser, IdentityResult };
|
|
30
|
+
export { ConfigurationError, IdentityError, isAdmin };
|
|
31
|
+
export type { EveryAppUser, IdentityResult, OrgRole };
|
|
22
32
|
/**
|
|
23
33
|
* The runtime's `ExecutionContext`, which `everyApp()` passes to the handler
|
|
24
34
|
* as the Worker received it, so it goes on to Hono's `app.fetch(request,
|
|
@@ -60,15 +70,25 @@ interface EveryAppExport<TEnv, TCtx extends ExecutionContextLike> {
|
|
|
60
70
|
}
|
|
61
71
|
/**
|
|
62
72
|
* Return the verified Every App user for this request, or null for a declared
|
|
63
|
-
* public request.
|
|
64
|
-
*
|
|
73
|
+
* public request. `request` is the inbound `Request` or just its `Headers`
|
|
74
|
+
* (a framework that hands out headers alone needs no made-up Request).
|
|
75
|
+
* Answers from the request context or the per-request cache first, then
|
|
76
|
+
* verifies the identity headers from the audience and public keys in env.
|
|
77
|
+
* Inside a handler `everyApp()` serves, `currentUser()` is the shorter way.
|
|
65
78
|
*/
|
|
66
|
-
export declare function getEveryAppUser(request: Request, env: object): Promise<EveryAppUser | null>;
|
|
79
|
+
export declare function getEveryAppUser(request: Request | Headers, env: object): Promise<EveryAppUser | null>;
|
|
67
80
|
/**
|
|
68
81
|
* Return the verified user, or throw the same 401 JSON Response shape as
|
|
69
82
|
* everyApp() when the request is public or unauthenticated.
|
|
70
83
|
*/
|
|
71
|
-
export declare function requireEveryAppUser(request: Request, env: object): Promise<EveryAppUser>;
|
|
84
|
+
export declare function requireEveryAppUser(request: Request | Headers, env: object): Promise<EveryAppUser>;
|
|
85
|
+
/**
|
|
86
|
+
* The user of the request being served (`currentUser()`), or throw the
|
|
87
|
+
* same 401 JSON Response as `requireEveryAppUser()` on a public route.
|
|
88
|
+
* Outside a request (`withOrganization()` work, a handler not under
|
|
89
|
+
* `everyApp()`) it throws `RequestContextError`, as `currentUser()` does.
|
|
90
|
+
*/
|
|
91
|
+
export declare function requireCurrentUser(): EveryAppUser;
|
|
72
92
|
export declare function hasScope(user: EveryAppUser, scope: string): boolean;
|
|
73
93
|
/** Wrap a Worker fetch handler with Every App identity verification. */
|
|
74
94
|
export declare function everyApp<TEnv = Record<string, unknown>, TCtx extends ExecutionContextLike = ExecutionContext>(handler: EveryAppHandler<TEnv, TCtx>, options?: EveryAppOptions): EveryAppExport<TEnv, TCtx>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"everyApp.d.ts","sourceRoot":"","sources":["../../src/server/everyApp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"everyApp.d.ts","sourceRoot":"","sources":["../../src/server/everyApp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAGL,kBAAkB,EAElB,aAAa,EAMb,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,OAAO,EAEb,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACtD,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0BAA0B;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,CACzB,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,IAAI,SAAS,oBAAoB,GAAG,gBAAgB,IAClD,CACF,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,IAAI,EACT,IAAI,EAAE,YAAY,GAAG,IAAI,KACtB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,UAAU,cAAc,CAAC,IAAI,EAAE,IAAI,SAAS,oBAAoB;IAC9D,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAClE;AAuKD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GAAG,OAAO,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAW9B;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,GAAG,OAAO,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,CAAC,CAevB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAMjD;AA0BD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AAUD,wEAAwE;AACxE,wBAAgB,QAAQ,CACtB,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,IAAI,SAAS,oBAAoB,GAAG,gBAAgB,EAEpD,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,EACpC,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC9B;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,IAAI,SAAS,oBAAoB,GAAG,gBAAgB,EAEpD,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,EACpC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,EAC1C,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC"}
|