@incorta/auth 1.0.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.
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/express.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ incortaAuth: () => incortaAuth,
24
+ requireAuth: () => requireAuth
25
+ });
26
+ module.exports = __toCommonJS(express_exports);
27
+
28
+ // src/node.ts
29
+ async function toWebRequest(req) {
30
+ const proto = req.headers["x-forwarded-proto"]?.split(",")[0]?.trim() ?? (req.socket.encrypted ? "https" : "http");
31
+ const host = req.headers.host ?? "localhost";
32
+ const path = req.originalUrl ?? req.url ?? "/";
33
+ const url = `${proto}://${host}${path}`;
34
+ const headers = new Headers();
35
+ for (let i = 0; i < req.rawHeaders.length; i += 2) {
36
+ headers.append(req.rawHeaders[i], req.rawHeaders[i + 1]);
37
+ }
38
+ const method = req.method ?? "GET";
39
+ let body;
40
+ if (method !== "GET" && method !== "HEAD") {
41
+ const chunks = [];
42
+ for await (const chunk of req) {
43
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
44
+ }
45
+ if (chunks.length) {
46
+ const bytes = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
47
+ let offset = 0;
48
+ for (const chunk of chunks) {
49
+ bytes.set(chunk, offset);
50
+ offset += chunk.length;
51
+ }
52
+ body = bytes;
53
+ }
54
+ }
55
+ return new Request(url, { method, headers, body });
56
+ }
57
+ async function sendWebResponse(res, response) {
58
+ res.statusCode = response.status;
59
+ response.headers.forEach((value, name) => {
60
+ if (name.toLowerCase() === "set-cookie") return;
61
+ res.setHeader(name, value);
62
+ });
63
+ const setCookies = response.headers.getSetCookie();
64
+ if (setCookies.length) res.setHeader("set-cookie", setCookies);
65
+ if (response.body) {
66
+ const buffer = Buffer.from(await response.arrayBuffer());
67
+ res.end(buffer);
68
+ } else {
69
+ res.end();
70
+ }
71
+ }
72
+ function toNodeHandler(auth) {
73
+ return async (req, res) => {
74
+ const request = await toWebRequest(req);
75
+ const response = await auth.handler(request);
76
+ await sendWebResponse(res, response);
77
+ };
78
+ }
79
+
80
+ // src/express.ts
81
+ function incortaAuth(auth) {
82
+ const nodeHandler = toNodeHandler(auth);
83
+ const { basePath } = auth.config;
84
+ return async (req, res, next) => {
85
+ try {
86
+ const path = (req.originalUrl ?? req.url ?? "/").split("?")[0];
87
+ if (path === basePath || path.startsWith(`${basePath}/`)) {
88
+ await nodeHandler(req, res);
89
+ return;
90
+ }
91
+ req.incortaAuth = await auth.getSession(await toWebRequest(req));
92
+ next();
93
+ } catch (error) {
94
+ next(error);
95
+ }
96
+ };
97
+ }
98
+ function requireAuth(auth, options = {}) {
99
+ const mode = options.unauthenticated ?? "auto";
100
+ const { basePath } = auth.config;
101
+ return async (req, res, next) => {
102
+ try {
103
+ if (req.incortaAuth === void 0) {
104
+ req.incortaAuth = await auth.getSession(await toWebRequest(req));
105
+ }
106
+ if (req.incortaAuth) {
107
+ next();
108
+ return;
109
+ }
110
+ const wantsHtml = (req.headers.accept ?? "").includes("text/html");
111
+ if (mode === "redirect" || mode === "auto" && wantsHtml) {
112
+ const returnTo = req.originalUrl ?? req.url ?? "/";
113
+ res.statusCode = 302;
114
+ res.setHeader(
115
+ "location",
116
+ `${basePath}/login?redirect_to=${encodeURIComponent(returnTo)}`
117
+ );
118
+ res.end();
119
+ return;
120
+ }
121
+ res.statusCode = 401;
122
+ res.setHeader("content-type", "application/json; charset=utf-8");
123
+ res.end(JSON.stringify({ error: "unauthenticated" }));
124
+ } catch (error) {
125
+ next(error);
126
+ }
127
+ };
128
+ }
129
+ // Annotate the CommonJS export names for ESM import in node:
130
+ 0 && (module.exports = {
131
+ incortaAuth,
132
+ requireAuth
133
+ });
134
+ //# sourceMappingURL=express.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/express.ts","../src/node.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AuthSession, IncortaAuth } from \"./index.js\";\nimport { toNodeHandler, toWebRequest } from \"./node.js\";\n\nexport type { AuthSession, IncortaAuth } from \"./index.js\";\n\n/**\n * Minimal structural types so this adapter works with Express 4/5 (and\n * anything Connect-compatible) without depending on Express itself.\n */\nexport interface AuthedRequest extends IncomingMessage {\n originalUrl?: string;\n /** Populated by `incortaAuth()`: the current session, or null when signed out. */\n incortaAuth?: AuthSession | null;\n}\ntype NextFunction = (err?: unknown) => void;\ntype Middleware = (\n req: AuthedRequest,\n res: ServerResponse,\n next: NextFunction,\n) => void | Promise<void>;\n\n/**\n * Express/Connect middleware that serves the auth routes (under\n * `auth.config.basePath`) and attaches the current session to every other\n * request as `req.incortaAuth`.\n *\n * ```ts\n * const auth = createIncortaAuth();\n * app.use(incortaAuth(auth));\n * app.get(\"/api/me\", requireAuth(auth), (req, res) => res.json(req.incortaAuth.user));\n * ```\n */\nexport function incortaAuth(auth: IncortaAuth): Middleware {\n const nodeHandler = toNodeHandler(auth);\n const { basePath } = auth.config;\n\n return async (req, res, next) => {\n try {\n const path = (req.originalUrl ?? req.url ?? \"/\").split(\"?\")[0];\n if (path === basePath || path.startsWith(`${basePath}/`)) {\n await nodeHandler(req, res);\n return;\n }\n req.incortaAuth = await auth.getSession(await toWebRequest(req));\n next();\n } catch (error) {\n next(error);\n }\n };\n}\n\nexport interface RequireAuthOptions {\n /**\n * How to reject unauthenticated requests:\n * - `\"redirect\"`: 302 to the login route (which bounces through Incorta login\n * and back to the original URL) — right for page routes.\n * - `\"json\"`: 401 `{ error: \"unauthenticated\" }` — right for API routes.\n * - `\"auto\"` (default): redirect when the request accepts text/html, 401 otherwise.\n */\n unauthenticated?: \"redirect\" | \"json\" | \"auto\";\n}\n\n/** Guards a route: only signed-in Incorta users get through. */\nexport function requireAuth(auth: IncortaAuth, options: RequireAuthOptions = {}): Middleware {\n const mode = options.unauthenticated ?? \"auto\";\n const { basePath } = auth.config;\n\n return async (req, res, next) => {\n try {\n if (req.incortaAuth === undefined) {\n req.incortaAuth = await auth.getSession(await toWebRequest(req));\n }\n if (req.incortaAuth) {\n next();\n return;\n }\n\n const wantsHtml = (req.headers.accept ?? \"\").includes(\"text/html\");\n if (mode === \"redirect\" || (mode === \"auto\" && wantsHtml)) {\n const returnTo = req.originalUrl ?? req.url ?? \"/\";\n res.statusCode = 302;\n res.setHeader(\n \"location\",\n `${basePath}/login?redirect_to=${encodeURIComponent(returnTo)}`,\n );\n res.end();\n return;\n }\n\n res.statusCode = 401;\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.end(JSON.stringify({ error: \"unauthenticated\" }));\n } catch (error) {\n next(error);\n }\n };\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { IncortaAuth } from \"./index.js\";\n\nexport type { IncortaAuth } from \"./index.js\";\n\n/**\n * Builds a web-standard `Request` from a Node request. Buffers the body (the\n * auth routes are GET/POST-without-body, so this stays tiny).\n */\nexport async function toWebRequest(req: IncomingMessage): Promise<Request> {\n const proto =\n (req.headers[\"x-forwarded-proto\"] as string | undefined)?.split(\",\")[0]?.trim() ??\n ((req.socket as { encrypted?: boolean }).encrypted ? \"https\" : \"http\");\n const host = req.headers.host ?? \"localhost\";\n // Express rewrites req.url when routers are mounted — originalUrl keeps the full path.\n const path = (req as { originalUrl?: string }).originalUrl ?? req.url ?? \"/\";\n const url = `${proto}://${host}${path}`;\n\n const headers = new Headers();\n for (let i = 0; i < req.rawHeaders.length; i += 2) {\n headers.append(req.rawHeaders[i], req.rawHeaders[i + 1]);\n }\n\n const method = req.method ?? \"GET\";\n let body: BodyInit | undefined;\n if (method !== \"GET\" && method !== \"HEAD\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n if (chunks.length) {\n const bytes = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.length;\n }\n body = bytes;\n }\n }\n\n return new Request(url, { method, headers, body });\n}\n\nexport async function sendWebResponse(\n res: ServerResponse,\n response: Response,\n): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, name) => {\n if (name.toLowerCase() === \"set-cookie\") return; // handled below, needs the un-joined list\n res.setHeader(name, value);\n });\n const setCookies = response.headers.getSetCookie();\n if (setCookies.length) res.setHeader(\"set-cookie\", setCookies);\n\n if (response.body) {\n const buffer = Buffer.from(await response.arrayBuffer());\n res.end(buffer);\n } else {\n res.end();\n }\n}\n\n/**\n * Adapts the auth handler to a plain Node `(req, res)` listener:\n *\n * ```ts\n * import http from \"node:http\";\n * const authListener = toNodeHandler(auth);\n * http.createServer((req, res) => {\n * if (req.url?.startsWith(\"/auth\")) return authListener(req, res);\n * // ... your app\n * });\n * ```\n */\nexport function toNodeHandler(auth: IncortaAuth) {\n return async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n const request = await toWebRequest(req);\n const response = await auth.handler(request);\n await sendWebResponse(res, response);\n };\n}\n\n/** Reads the current session from a Node request (returns null when signed out). */\nexport async function getNodeSession(auth: IncortaAuth, req: IncomingMessage) {\n return auth.getSession(await toWebRequest(req));\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,42 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { AuthSession, IncortaAuth } from './index.cjs';
3
+ import './config-B-2cbZDV.cjs';
4
+ import 'jose';
5
+
6
+ /**
7
+ * Minimal structural types so this adapter works with Express 4/5 (and
8
+ * anything Connect-compatible) without depending on Express itself.
9
+ */
10
+ interface AuthedRequest extends IncomingMessage {
11
+ originalUrl?: string;
12
+ /** Populated by `incortaAuth()`: the current session, or null when signed out. */
13
+ incortaAuth?: AuthSession | null;
14
+ }
15
+ type NextFunction = (err?: unknown) => void;
16
+ type Middleware = (req: AuthedRequest, res: ServerResponse, next: NextFunction) => void | Promise<void>;
17
+ /**
18
+ * Express/Connect middleware that serves the auth routes (under
19
+ * `auth.config.basePath`) and attaches the current session to every other
20
+ * request as `req.incortaAuth`.
21
+ *
22
+ * ```ts
23
+ * const auth = createIncortaAuth();
24
+ * app.use(incortaAuth(auth));
25
+ * app.get("/api/me", requireAuth(auth), (req, res) => res.json(req.incortaAuth.user));
26
+ * ```
27
+ */
28
+ declare function incortaAuth(auth: IncortaAuth): Middleware;
29
+ interface RequireAuthOptions {
30
+ /**
31
+ * How to reject unauthenticated requests:
32
+ * - `"redirect"`: 302 to the login route (which bounces through Incorta login
33
+ * and back to the original URL) — right for page routes.
34
+ * - `"json"`: 401 `{ error: "unauthenticated" }` — right for API routes.
35
+ * - `"auto"` (default): redirect when the request accepts text/html, 401 otherwise.
36
+ */
37
+ unauthenticated?: "redirect" | "json" | "auto";
38
+ }
39
+ /** Guards a route: only signed-in Incorta users get through. */
40
+ declare function requireAuth(auth: IncortaAuth, options?: RequireAuthOptions): Middleware;
41
+
42
+ export { AuthSession, type AuthedRequest, IncortaAuth, type RequireAuthOptions, incortaAuth, requireAuth };
@@ -0,0 +1,42 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { AuthSession, IncortaAuth } from './index.js';
3
+ import './config-B-2cbZDV.js';
4
+ import 'jose';
5
+
6
+ /**
7
+ * Minimal structural types so this adapter works with Express 4/5 (and
8
+ * anything Connect-compatible) without depending on Express itself.
9
+ */
10
+ interface AuthedRequest extends IncomingMessage {
11
+ originalUrl?: string;
12
+ /** Populated by `incortaAuth()`: the current session, or null when signed out. */
13
+ incortaAuth?: AuthSession | null;
14
+ }
15
+ type NextFunction = (err?: unknown) => void;
16
+ type Middleware = (req: AuthedRequest, res: ServerResponse, next: NextFunction) => void | Promise<void>;
17
+ /**
18
+ * Express/Connect middleware that serves the auth routes (under
19
+ * `auth.config.basePath`) and attaches the current session to every other
20
+ * request as `req.incortaAuth`.
21
+ *
22
+ * ```ts
23
+ * const auth = createIncortaAuth();
24
+ * app.use(incortaAuth(auth));
25
+ * app.get("/api/me", requireAuth(auth), (req, res) => res.json(req.incortaAuth.user));
26
+ * ```
27
+ */
28
+ declare function incortaAuth(auth: IncortaAuth): Middleware;
29
+ interface RequireAuthOptions {
30
+ /**
31
+ * How to reject unauthenticated requests:
32
+ * - `"redirect"`: 302 to the login route (which bounces through Incorta login
33
+ * and back to the original URL) — right for page routes.
34
+ * - `"json"`: 401 `{ error: "unauthenticated" }` — right for API routes.
35
+ * - `"auto"` (default): redirect when the request accepts text/html, 401 otherwise.
36
+ */
37
+ unauthenticated?: "redirect" | "json" | "auto";
38
+ }
39
+ /** Guards a route: only signed-in Incorta users get through. */
40
+ declare function requireAuth(auth: IncortaAuth, options?: RequireAuthOptions): Middleware;
41
+
42
+ export { AuthSession, type AuthedRequest, IncortaAuth, type RequireAuthOptions, incortaAuth, requireAuth };
@@ -0,0 +1,59 @@
1
+ import {
2
+ toNodeHandler,
3
+ toWebRequest
4
+ } from "./chunk-LNPECE7W.js";
5
+
6
+ // src/express.ts
7
+ function incortaAuth(auth) {
8
+ const nodeHandler = toNodeHandler(auth);
9
+ const { basePath } = auth.config;
10
+ return async (req, res, next) => {
11
+ try {
12
+ const path = (req.originalUrl ?? req.url ?? "/").split("?")[0];
13
+ if (path === basePath || path.startsWith(`${basePath}/`)) {
14
+ await nodeHandler(req, res);
15
+ return;
16
+ }
17
+ req.incortaAuth = await auth.getSession(await toWebRequest(req));
18
+ next();
19
+ } catch (error) {
20
+ next(error);
21
+ }
22
+ };
23
+ }
24
+ function requireAuth(auth, options = {}) {
25
+ const mode = options.unauthenticated ?? "auto";
26
+ const { basePath } = auth.config;
27
+ return async (req, res, next) => {
28
+ try {
29
+ if (req.incortaAuth === void 0) {
30
+ req.incortaAuth = await auth.getSession(await toWebRequest(req));
31
+ }
32
+ if (req.incortaAuth) {
33
+ next();
34
+ return;
35
+ }
36
+ const wantsHtml = (req.headers.accept ?? "").includes("text/html");
37
+ if (mode === "redirect" || mode === "auto" && wantsHtml) {
38
+ const returnTo = req.originalUrl ?? req.url ?? "/";
39
+ res.statusCode = 302;
40
+ res.setHeader(
41
+ "location",
42
+ `${basePath}/login?redirect_to=${encodeURIComponent(returnTo)}`
43
+ );
44
+ res.end();
45
+ return;
46
+ }
47
+ res.statusCode = 401;
48
+ res.setHeader("content-type", "application/json; charset=utf-8");
49
+ res.end(JSON.stringify({ error: "unauthenticated" }));
50
+ } catch (error) {
51
+ next(error);
52
+ }
53
+ };
54
+ }
55
+ export {
56
+ incortaAuth,
57
+ requireAuth
58
+ };
59
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/express.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AuthSession, IncortaAuth } from \"./index.js\";\nimport { toNodeHandler, toWebRequest } from \"./node.js\";\n\nexport type { AuthSession, IncortaAuth } from \"./index.js\";\n\n/**\n * Minimal structural types so this adapter works with Express 4/5 (and\n * anything Connect-compatible) without depending on Express itself.\n */\nexport interface AuthedRequest extends IncomingMessage {\n originalUrl?: string;\n /** Populated by `incortaAuth()`: the current session, or null when signed out. */\n incortaAuth?: AuthSession | null;\n}\ntype NextFunction = (err?: unknown) => void;\ntype Middleware = (\n req: AuthedRequest,\n res: ServerResponse,\n next: NextFunction,\n) => void | Promise<void>;\n\n/**\n * Express/Connect middleware that serves the auth routes (under\n * `auth.config.basePath`) and attaches the current session to every other\n * request as `req.incortaAuth`.\n *\n * ```ts\n * const auth = createIncortaAuth();\n * app.use(incortaAuth(auth));\n * app.get(\"/api/me\", requireAuth(auth), (req, res) => res.json(req.incortaAuth.user));\n * ```\n */\nexport function incortaAuth(auth: IncortaAuth): Middleware {\n const nodeHandler = toNodeHandler(auth);\n const { basePath } = auth.config;\n\n return async (req, res, next) => {\n try {\n const path = (req.originalUrl ?? req.url ?? \"/\").split(\"?\")[0];\n if (path === basePath || path.startsWith(`${basePath}/`)) {\n await nodeHandler(req, res);\n return;\n }\n req.incortaAuth = await auth.getSession(await toWebRequest(req));\n next();\n } catch (error) {\n next(error);\n }\n };\n}\n\nexport interface RequireAuthOptions {\n /**\n * How to reject unauthenticated requests:\n * - `\"redirect\"`: 302 to the login route (which bounces through Incorta login\n * and back to the original URL) — right for page routes.\n * - `\"json\"`: 401 `{ error: \"unauthenticated\" }` — right for API routes.\n * - `\"auto\"` (default): redirect when the request accepts text/html, 401 otherwise.\n */\n unauthenticated?: \"redirect\" | \"json\" | \"auto\";\n}\n\n/** Guards a route: only signed-in Incorta users get through. */\nexport function requireAuth(auth: IncortaAuth, options: RequireAuthOptions = {}): Middleware {\n const mode = options.unauthenticated ?? \"auto\";\n const { basePath } = auth.config;\n\n return async (req, res, next) => {\n try {\n if (req.incortaAuth === undefined) {\n req.incortaAuth = await auth.getSession(await toWebRequest(req));\n }\n if (req.incortaAuth) {\n next();\n return;\n }\n\n const wantsHtml = (req.headers.accept ?? \"\").includes(\"text/html\");\n if (mode === \"redirect\" || (mode === \"auto\" && wantsHtml)) {\n const returnTo = req.originalUrl ?? req.url ?? \"/\";\n res.statusCode = 302;\n res.setHeader(\n \"location\",\n `${basePath}/login?redirect_to=${encodeURIComponent(returnTo)}`,\n );\n res.end();\n return;\n }\n\n res.statusCode = 401;\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.end(JSON.stringify({ error: \"unauthenticated\" }));\n } catch (error) {\n next(error);\n }\n };\n}\n"],"mappings":";;;;;;AAiCO,SAAS,YAAY,MAA+B;AACzD,QAAM,cAAc,cAAc,IAAI;AACtC,QAAM,EAAE,SAAS,IAAI,KAAK;AAE1B,SAAO,OAAO,KAAK,KAAK,SAAS;AAC/B,QAAI;AACF,YAAM,QAAQ,IAAI,eAAe,IAAI,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAC7D,UAAI,SAAS,YAAY,KAAK,WAAW,GAAG,QAAQ,GAAG,GAAG;AACxD,cAAM,YAAY,KAAK,GAAG;AAC1B;AAAA,MACF;AACA,UAAI,cAAc,MAAM,KAAK,WAAW,MAAM,aAAa,GAAG,CAAC;AAC/D,WAAK;AAAA,IACP,SAAS,OAAO;AACd,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;AAcO,SAAS,YAAY,MAAmB,UAA8B,CAAC,GAAe;AAC3F,QAAM,OAAO,QAAQ,mBAAmB;AACxC,QAAM,EAAE,SAAS,IAAI,KAAK;AAE1B,SAAO,OAAO,KAAK,KAAK,SAAS;AAC/B,QAAI;AACF,UAAI,IAAI,gBAAgB,QAAW;AACjC,YAAI,cAAc,MAAM,KAAK,WAAW,MAAM,aAAa,GAAG,CAAC;AAAA,MACjE;AACA,UAAI,IAAI,aAAa;AACnB,aAAK;AACL;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,QAAQ,UAAU,IAAI,SAAS,WAAW;AACjE,UAAI,SAAS,cAAe,SAAS,UAAU,WAAY;AACzD,cAAM,WAAW,IAAI,eAAe,IAAI,OAAO;AAC/C,YAAI,aAAa;AACjB,YAAI;AAAA,UACF;AAAA,UACA,GAAG,QAAQ,sBAAsB,mBAAmB,QAAQ,CAAC;AAAA,QAC/D;AACA,YAAI,IAAI;AACR;AAAA,MACF;AAEA,UAAI,aAAa;AACjB,UAAI,UAAU,gBAAgB,iCAAiC;AAC/D,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,kBAAkB,CAAC,CAAC;AAAA,IACtD,SAAS,OAAO;AACd,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;","names":[]}