@01.software/sdk 0.1.8 → 0.1.9
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 +14 -2
- package/dist/index.cjs +65 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +65 -12
- package/dist/index.js.map +1 -1
- package/dist/webhook.cjs +4 -5
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.js +4 -5
- package/dist/webhook.js.map +1 -1
- package/package.json +1 -1
package/dist/webhook.cjs
CHANGED
|
@@ -76,11 +76,6 @@ function handleWebhook(request, handler, options) {
|
|
|
76
76
|
return __async(this, null, function* () {
|
|
77
77
|
try {
|
|
78
78
|
const rawBody = yield request.text();
|
|
79
|
-
if (!(options == null ? void 0 : options.secret)) {
|
|
80
|
-
console.warn(
|
|
81
|
-
"[@01.software/sdk] Webhook signature verification is skipped because no secret was provided. Pass { secret } to handleWebhook() to enable signature verification."
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
79
|
if (options == null ? void 0 : options.secret) {
|
|
85
80
|
const signature = request.headers.get("x-webhook-signature") || "";
|
|
86
81
|
const valid = yield verifySignature(rawBody, options.secret, signature);
|
|
@@ -90,6 +85,10 @@ function handleWebhook(request, handler, options) {
|
|
|
90
85
|
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
91
86
|
);
|
|
92
87
|
}
|
|
88
|
+
} else {
|
|
89
|
+
console.warn(
|
|
90
|
+
"[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
|
|
91
|
+
);
|
|
93
92
|
}
|
|
94
93
|
const body = JSON.parse(rawBody);
|
|
95
94
|
if (!isValidWebhookEvent(body)) {
|
package/dist/webhook.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.tsx"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n isValidWebhookEvent,\n} from './core/webhook'\nexport type {\n WebhookEvent,\n WebhookHandler,\n WebhookOperation,\n WebhookOptions,\n} from './core/webhook'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n let result = expected.length !== signature.length ? 1 : 0\n const len = Math.max(expected.length, signature.length)\n for (let i = 0; i < len; i++) {\n result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (
|
|
1
|
+
{"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.tsx"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n isValidWebhookEvent,\n} from './core/webhook'\nexport type {\n WebhookEvent,\n WebhookHandler,\n WebhookOperation,\n WebhookOptions,\n} from './core/webhook'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n let result = expected.length !== signature.length ? 1 : 0\n const len = Math.max(expected.length, signature.length)\n for (let i = 0; i < len; i++) {\n result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const valid = await verifySignature(rawBody, options.secret, signature)\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n } else {\n console.warn(\n '[@01.software/sdk] Webhook signature verification is disabled. ' +\n 'Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification.',\n )\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(\n JSON.stringify({ error: 'Internal server error' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(`Expected collection \"${collection}\", got \"${event.collection}\"`)\n }\n return handler(event)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmBO,SAAS,oBAAoB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,eAAe,aACzB,IAAI,cAAc,YAAY,IAAI,cAAc,aACjD,OAAO,IAAI,SAAS,YACpB,IAAI,SAAS;AAEjB;AAEA,SAAe,gBACb,SACA,QACA,WACkB;AAAA;AAClB,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,MAAM,MAAM,OAAO,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ,OAAO,MAAM;AAAA,MACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC;AAAA,MACA,CAAC,MAAM;AAAA,IACT;AACA,UAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC;AACzE,UAAM,WAAW,MAAM,KAAK,IAAI,WAAW,GAAG,CAAC,EAC5C,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AAEV,QAAI,SAAS,SAAS,WAAW,UAAU,SAAS,IAAI;AACxD,UAAM,MAAM,KAAK,IAAI,SAAS,QAAQ,UAAU,MAAM;AACtD,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,iBAAW,SAAS,WAAW,CAAC,KAAK,MAAM,UAAU,WAAW,CAAC,KAAK;AAAA,IACxE;AACA,WAAO,WAAW;AAAA,EACpB;AAAA;AAEA,SAAsB,cACpB,SACA,SACA,SACmB;AAAA;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,UAAI,mCAAS,QAAQ;AACnB,cAAM,YAAY,QAAQ,QAAQ,IAAI,qBAAqB,KAAK;AAChE,cAAM,QAAQ,MAAM,gBAAgB,SAAS,QAAQ,QAAQ,SAAS;AACtE,YAAI,CAAC,OAAO;AACV,iBAAO,IAAI;AAAA,YACT,KAAK,UAAU,EAAE,OAAO,4BAA4B,CAAC;AAAA,YACrD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,UACjE;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA,QAEF;AAAA,MACF;AAEA,YAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,UAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,eAAO,IAAI;AAAA,UACT,KAAK,UAAU,EAAE,OAAO,+BAA+B,CAAC;AAAA,UACxD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,QACjE;AAAA,MACF;AAEA,YAAM,QAAQ,IAAuB;AAErC,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,SAAS,MAAM,SAAS,oBAAoB,CAAC;AAAA,QAC9D,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAEhD,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,OAAO,wBAAwB,CAAC;AAAA,QACjD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAEO,SAAS,0BACd,YACA,SACmB;AACnB,SAAO,CAAO,UAA2B;AACvC,QAAI,MAAM,eAAe,YAAY;AACnC,YAAM,IAAI,MAAM,wBAAwB,UAAU,WAAW,MAAM,UAAU,GAAG;AAAA,IAClF;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;","names":[]}
|
package/dist/webhook.js
CHANGED
|
@@ -49,11 +49,6 @@ function handleWebhook(request, handler, options) {
|
|
|
49
49
|
return __async(this, null, function* () {
|
|
50
50
|
try {
|
|
51
51
|
const rawBody = yield request.text();
|
|
52
|
-
if (!(options == null ? void 0 : options.secret)) {
|
|
53
|
-
console.warn(
|
|
54
|
-
"[@01.software/sdk] Webhook signature verification is skipped because no secret was provided. Pass { secret } to handleWebhook() to enable signature verification."
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
52
|
if (options == null ? void 0 : options.secret) {
|
|
58
53
|
const signature = request.headers.get("x-webhook-signature") || "";
|
|
59
54
|
const valid = yield verifySignature(rawBody, options.secret, signature);
|
|
@@ -63,6 +58,10 @@ function handleWebhook(request, handler, options) {
|
|
|
63
58
|
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
64
59
|
);
|
|
65
60
|
}
|
|
61
|
+
} else {
|
|
62
|
+
console.warn(
|
|
63
|
+
"[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
|
|
64
|
+
);
|
|
66
65
|
}
|
|
67
66
|
const body = JSON.parse(rawBody);
|
|
68
67
|
if (!isValidWebhookEvent(body)) {
|
package/dist/webhook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/webhook/index.tsx"],"sourcesContent":["import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n let result = expected.length !== signature.length ? 1 : 0\n const len = Math.max(expected.length, signature.length)\n for (let i = 0; i < len; i++) {\n result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (
|
|
1
|
+
{"version":3,"sources":["../src/core/webhook/index.tsx"],"sourcesContent":["import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n let result = expected.length !== signature.length ? 1 : 0\n const len = Math.max(expected.length, signature.length)\n for (let i = 0; i < len; i++) {\n result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const valid = await verifySignature(rawBody, options.secret, signature)\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n } else {\n console.warn(\n '[@01.software/sdk] Webhook signature verification is disabled. ' +\n 'Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification.',\n )\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(\n JSON.stringify({ error: 'Internal server error' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(`Expected collection \"${collection}\", got \"${event.collection}\"`)\n }\n return handler(event)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmBO,SAAS,oBAAoB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,eAAe,aACzB,IAAI,cAAc,YAAY,IAAI,cAAc,aACjD,OAAO,IAAI,SAAS,YACpB,IAAI,SAAS;AAEjB;AAEA,SAAe,gBACb,SACA,QACA,WACkB;AAAA;AAClB,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,MAAM,MAAM,OAAO,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ,OAAO,MAAM;AAAA,MACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC;AAAA,MACA,CAAC,MAAM;AAAA,IACT;AACA,UAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC;AACzE,UAAM,WAAW,MAAM,KAAK,IAAI,WAAW,GAAG,CAAC,EAC5C,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AAEV,QAAI,SAAS,SAAS,WAAW,UAAU,SAAS,IAAI;AACxD,UAAM,MAAM,KAAK,IAAI,SAAS,QAAQ,UAAU,MAAM;AACtD,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,iBAAW,SAAS,WAAW,CAAC,KAAK,MAAM,UAAU,WAAW,CAAC,KAAK;AAAA,IACxE;AACA,WAAO,WAAW;AAAA,EACpB;AAAA;AAEA,SAAsB,cACpB,SACA,SACA,SACmB;AAAA;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,UAAI,mCAAS,QAAQ;AACnB,cAAM,YAAY,QAAQ,QAAQ,IAAI,qBAAqB,KAAK;AAChE,cAAM,QAAQ,MAAM,gBAAgB,SAAS,QAAQ,QAAQ,SAAS;AACtE,YAAI,CAAC,OAAO;AACV,iBAAO,IAAI;AAAA,YACT,KAAK,UAAU,EAAE,OAAO,4BAA4B,CAAC;AAAA,YACrD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,UACjE;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA,QAEF;AAAA,MACF;AAEA,YAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,UAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,eAAO,IAAI;AAAA,UACT,KAAK,UAAU,EAAE,OAAO,+BAA+B,CAAC;AAAA,UACxD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,QACjE;AAAA,MACF;AAEA,YAAM,QAAQ,IAAuB;AAErC,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,SAAS,MAAM,SAAS,oBAAoB,CAAC;AAAA,QAC9D,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAEhD,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,OAAO,wBAAwB,CAAC;AAAA,QACjD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAEO,SAAS,0BACd,YACA,SACmB;AACnB,SAAO,CAAO,UAA2B;AACvC,QAAI,MAAM,eAAe,YAAY;AACnC,YAAM,IAAI,MAAM,wBAAwB,UAAU,WAAW,MAAM,UAAU,GAAG;AAAA,IAClF;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;","names":[]}
|