@webiny/background-tasks-aws 0.0.0-unstable.5387e5f7c8 → 0.0.0-unstable.eb81deee7e
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/BackgroundTaskLambdaHandler.d.ts +3 -3
- package/BackgroundTaskLambdaHandler.js +2 -1
- package/BackgroundTaskLambdaHandler.js.map +1 -1
- package/package.json +10 -10
- package/service/StepFunctionService.d.ts +1 -3
- package/service/StepFunctionService.js +10 -15
- package/service/StepFunctionService.js.map +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Container } from "@webiny/feature/api";
|
|
2
|
-
import { BackgroundTaskEventHandler } from "@webiny/event-handler-
|
|
2
|
+
import { BackgroundTaskEventHandler } from "@webiny/event-handler-aws/abstractions/handlers/BackgroundTaskEventHandler.js";
|
|
3
3
|
import type { EventContext, NextFunction } from "@webiny/event-handler-core";
|
|
4
|
-
import type { IBackgroundTaskEvent } from "@webiny/event-handler-
|
|
4
|
+
import type { IBackgroundTaskEvent } from "@webiny/event-handler-aws/eventTypes/BackgroundTaskEventType.js";
|
|
5
5
|
declare class BackgroundTaskLambdaHandlerImpl implements BackgroundTaskEventHandler.Interface {
|
|
6
6
|
private container;
|
|
7
7
|
constructor(container: Container);
|
|
8
8
|
execute(eventCtx: EventContext<IBackgroundTaskEvent>, _next: NextFunction): Promise<unknown>;
|
|
9
9
|
}
|
|
10
10
|
export declare const BackgroundTaskLambdaHandler: typeof BackgroundTaskLambdaHandlerImpl & {
|
|
11
|
-
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-
|
|
11
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws/abstractions/handlers/BackgroundTaskEventHandler.js").IBackgroundTaskEventHandler>;
|
|
12
12
|
};
|
|
13
13
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AwsLambdaContext } from "@webiny/event-handler-aws/abstractions/AwsLambdaContext.js";
|
|
2
|
-
import { BackgroundTaskEventHandler
|
|
2
|
+
import { BackgroundTaskEventHandler } from "@webiny/event-handler-aws/abstractions/handlers/BackgroundTaskEventHandler.js";
|
|
3
|
+
import { RequestContainer } from "@webiny/event-handler-core";
|
|
3
4
|
import { RawTenantId, RequestTenantLoader } from "@webiny/api-core/features/requestContext/index.js";
|
|
4
5
|
import { TaskRunner } from "@webiny/background-tasks/api/runner/index.js";
|
|
5
6
|
import { TaskEventValidation } from "@webiny/background-tasks/api/runner/TaskEventValidation.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackgroundTaskLambdaHandler.js","sources":["../src/BackgroundTaskLambdaHandler.ts"],"sourcesContent":["import type { Container } from \"@webiny/feature/api\";\nimport { AwsLambdaContext } from \"@webiny/event-handler-aws/abstractions/AwsLambdaContext.js\";\nimport { BackgroundTaskEventHandler } from \"@webiny/event-handler-
|
|
1
|
+
{"version":3,"file":"BackgroundTaskLambdaHandler.js","sources":["../src/BackgroundTaskLambdaHandler.ts"],"sourcesContent":["import type { Container } from \"@webiny/feature/api\";\nimport { AwsLambdaContext } from \"@webiny/event-handler-aws/abstractions/AwsLambdaContext.js\";\nimport { BackgroundTaskEventHandler } from \"@webiny/event-handler-aws/abstractions/handlers/BackgroundTaskEventHandler.js\";\nimport { RequestContainer } from \"@webiny/event-handler-core\";\nimport {\n RawTenantId,\n RequestTenantLoader\n} from \"@webiny/api-core/features/requestContext/index.js\";\nimport type { EventContext, NextFunction } from \"@webiny/event-handler-core\";\nimport type { IBackgroundTaskEvent } from \"@webiny/event-handler-aws/eventTypes/BackgroundTaskEventType.js\";\nimport { TaskRunner } from \"@webiny/background-tasks/api/runner/index.js\";\nimport { TaskEventValidation } from \"@webiny/background-tasks/api/runner/TaskEventValidation.js\";\nimport type { Context } from \"@webiny/background-tasks/api/types.js\";\nimport { LambdaTimer } from \"~/timer/LambdaTimer.js\";\n\n/* Fallback ceiling used when there is no real Lambda context to read the remaining time from\n * (mirrors the default Lambda timeout budget handler-aws's CustomTimer uses). */\nconst FALLBACK_MAX_RUNNING_MILLISECONDS = 14 * 60 * 1000;\n\nclass BackgroundTaskLambdaHandlerImpl implements BackgroundTaskEventHandler.Interface {\n constructor(private container: Container) {}\n\n async execute(\n eventCtx: EventContext<IBackgroundTaskEvent>,\n _next: NextFunction\n ): Promise<unknown> {\n // Date-based fallback in case there is no real Lambda context (see below) — captured up\n // front so the fallback countdown starts at the beginning of this invocation.\n const fallbackStartTime = Date.now();\n // The SFN/EventBridge transport wraps the task as `{ name, payload }`; TaskRunner expects the\n // flat task event (webinyTaskId at top level), so unwrap `payload` (falling back to the event\n // itself if it's already flat).\n const taskEvent = (eventCtx.event as any)?.payload || eventCtx.event;\n\n // Background tasks have no HTTP request establisher. This is the bg-task EXTRACT step: put the\n // tenant id from the task event into RawTenantId, then run the shared LOAD step\n // (RequestTenantLoader) — same tenant-establishment path as every other transport. The\n // CRUD (TasksCrud) and downstream use cases resolve the current tenant, so it must be set\n // before the task runs.\n if (taskEvent?.tenant) {\n this.container.resolve(RawTenantId).set(taskEvent.tenant);\n await this.container.resolve(RequestTenantLoader).establish();\n }\n\n // TaskRunner still takes the legacy context object, which now only carries the container.\n const ctx: Record<string, any> = { container: this.container };\n\n // Use the real Lambda context's countdown when the invocation has one; otherwise fall back\n // to a Date-based countdown so the timer still winds down instead of staying static.\n const lambdaContext = this.container.resolve(AwsLambdaContext);\n const timer = new LambdaTimer({\n getRemainingTimeInMillis: () => {\n if (lambdaContext.isSet()) {\n return lambdaContext.get().getRemainingTimeInMillis();\n }\n return fallbackStartTime + FALLBACK_MAX_RUNNING_MILLISECONDS - Date.now();\n }\n });\n const runner = new TaskRunner(ctx as Context, timer, new TaskEventValidation());\n\n // Return the task result — the SFN reads `$.status` (continue/done/error) from it to drive\n // the state machine. Returning void makes the SFN see null → UnknownError → FAILED.\n return runner.run(taskEvent);\n }\n}\n\nexport const BackgroundTaskLambdaHandler = BackgroundTaskEventHandler.createImplementation({\n implementation: BackgroundTaskLambdaHandlerImpl,\n dependencies: [RequestContainer]\n});\n"],"names":["FALLBACK_MAX_RUNNING_MILLISECONDS","BackgroundTaskLambdaHandlerImpl","container","eventCtx","_next","fallbackStartTime","Date","taskEvent","RawTenantId","RequestTenantLoader","ctx","lambdaContext","AwsLambdaContext","timer","LambdaTimer","runner","TaskRunner","TaskEventValidation","BackgroundTaskLambdaHandler","BackgroundTaskEventHandler","RequestContainer"],"mappings":";;;;;;;AAiBA,MAAMA,oCAAoC;AAE1C,MAAMC;IACF,YAAoBC,SAAoB,CAAE;aAAtBA,SAAS,GAATA;IAAuB;IAE3C,MAAM,QACFC,QAA4C,EAC5CC,KAAmB,EACH;QAGhB,MAAMC,oBAAoBC,KAAK,GAAG;QAIlC,MAAMC,YAAaJ,SAAS,KAAK,EAAU,WAAWA,SAAS,KAAK;QAOpE,IAAII,WAAW,QAAQ;YACnB,IAAI,CAAC,SAAS,CAAC,OAAO,CAACC,aAAa,GAAG,CAACD,UAAU,MAAM;YACxD,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAACE,qBAAqB,SAAS;QAC/D;QAGA,MAAMC,MAA2B;YAAE,WAAW,IAAI,CAAC,SAAS;QAAC;QAI7D,MAAMC,gBAAgB,IAAI,CAAC,SAAS,CAAC,OAAO,CAACC;QAC7C,MAAMC,QAAQ,IAAIC,YAAY;YAC1B,0BAA0B;gBACtB,IAAIH,cAAc,KAAK,IACnB,OAAOA,cAAc,GAAG,GAAG,wBAAwB;gBAEvD,OAAON,oBAAoBL,oCAAoCM,KAAK,GAAG;YAC3E;QACJ;QACA,MAAMS,SAAS,IAAIC,WAAWN,KAAgBG,OAAO,IAAII;QAIzD,OAAOF,OAAO,GAAG,CAACR;IACtB;AACJ;AAEO,MAAMW,8BAA8BC,2BAA2B,oBAAoB,CAAC;IACvF,gBAAgBlB;IAChB,cAAc;QAACmB;KAAiB;AACpC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/background-tasks-aws",
|
|
3
|
-
"version": "0.0.0-unstable.
|
|
3
|
+
"version": "0.0.0-unstable.eb81deee7e",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
},
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@webiny/api-core": "0.0.0-unstable.
|
|
18
|
-
"@webiny/aws-sdk": "0.0.0-unstable.
|
|
19
|
-
"@webiny/background-tasks": "0.0.0-unstable.
|
|
20
|
-
"@webiny/event-handler-aws": "0.0.0-unstable.
|
|
21
|
-
"@webiny/event-handler-core": "0.0.0-unstable.
|
|
22
|
-
"@webiny/feature": "0.0.0-unstable.
|
|
23
|
-
"@webiny/utils": "0.0.0-unstable.
|
|
17
|
+
"@webiny/api-core": "0.0.0-unstable.eb81deee7e",
|
|
18
|
+
"@webiny/aws-sdk": "0.0.0-unstable.eb81deee7e",
|
|
19
|
+
"@webiny/background-tasks": "0.0.0-unstable.eb81deee7e",
|
|
20
|
+
"@webiny/event-handler-aws": "0.0.0-unstable.eb81deee7e",
|
|
21
|
+
"@webiny/event-handler-core": "0.0.0-unstable.eb81deee7e",
|
|
22
|
+
"@webiny/feature": "0.0.0-unstable.eb81deee7e",
|
|
23
|
+
"@webiny/utils": "0.0.0-unstable.eb81deee7e"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@webiny/build-tools": "0.0.0-unstable.
|
|
27
|
-
"@webiny/di": "
|
|
26
|
+
"@webiny/build-tools": "0.0.0-unstable.eb81deee7e",
|
|
27
|
+
"@webiny/di": "1.1.0",
|
|
28
28
|
"rimraf": "6.1.3",
|
|
29
29
|
"typescript": "7.0.2",
|
|
30
30
|
"vitest": "4.1.11"
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import type { DescribeExecutionCommandOutput } from "@webiny/aws-sdk/client-sfn/index.js";
|
|
2
2
|
import { TaskService } from "@webiny/background-tasks/api/domain/TaskService.js";
|
|
3
3
|
import { TenantContext } from "@webiny/api-core/exports/api/tenancy.js";
|
|
4
|
-
import { Logger } from "@webiny/api-core/features/logger/index.js";
|
|
5
4
|
export type IStepFunctionServiceFetchResult = DescribeExecutionCommandOutput;
|
|
6
5
|
export interface IDetailWrapper<T> {
|
|
7
6
|
detail: T;
|
|
8
7
|
}
|
|
9
8
|
declare class StepFunctionServiceImpl implements TaskService.Interface {
|
|
10
9
|
private readonly tenantContext;
|
|
11
|
-
private readonly logger;
|
|
12
10
|
private readonly trigger;
|
|
13
11
|
private readonly get;
|
|
14
|
-
constructor(tenantContext: TenantContext.Interface
|
|
12
|
+
constructor(tenantContext: TenantContext.Interface);
|
|
15
13
|
send(task: TaskService.SendTaskParams, delay: number): Promise<{
|
|
16
14
|
$metadata: import("@smithy/types").ResponseMetadata;
|
|
17
15
|
executionArn: string | undefined;
|
|
@@ -3,11 +3,9 @@ import { generateAlphaNumericId } from "@webiny/utils";
|
|
|
3
3
|
import { ServiceDiscovery } from "@webiny/api-core/features/serviceDiscovery/index.js";
|
|
4
4
|
import { TaskService } from "@webiny/background-tasks/api/domain/TaskService.js";
|
|
5
5
|
import { TenantContext } from "@webiny/api-core/exports/api/tenancy.js";
|
|
6
|
-
import { Logger } from "@webiny/api-core/features/logger/index.js";
|
|
7
6
|
class StepFunctionServiceImpl {
|
|
8
|
-
constructor(tenantContext
|
|
7
|
+
constructor(tenantContext){
|
|
9
8
|
this.tenantContext = tenantContext;
|
|
10
|
-
this.logger = logger;
|
|
11
9
|
const client = createStepFunctionClient();
|
|
12
10
|
this.trigger = triggerStepFunctionFactory(client);
|
|
13
11
|
this.get = describeExecutionFactory(client);
|
|
@@ -15,17 +13,17 @@ class StepFunctionServiceImpl {
|
|
|
15
13
|
async send(task, delay) {
|
|
16
14
|
const manifest = await ServiceDiscovery.load();
|
|
17
15
|
if (!manifest) {
|
|
18
|
-
|
|
16
|
+
console.error("Service manifest not found.");
|
|
19
17
|
return null;
|
|
20
18
|
}
|
|
21
19
|
const { bgTaskSfn } = manifest.api || {};
|
|
22
20
|
if (!bgTaskSfn) {
|
|
23
|
-
|
|
21
|
+
console.error("Background task state machine not found.");
|
|
24
22
|
return null;
|
|
25
23
|
}
|
|
26
24
|
const tenant = this.tenantContext.getTenant();
|
|
27
25
|
if (!tenant) {
|
|
28
|
-
|
|
26
|
+
console.error("Tenant not found.");
|
|
29
27
|
return null;
|
|
30
28
|
}
|
|
31
29
|
const input = {
|
|
@@ -48,16 +46,15 @@ class StepFunctionServiceImpl {
|
|
|
48
46
|
name
|
|
49
47
|
};
|
|
50
48
|
} catch (ex) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}, "Could not trigger a step function.");
|
|
49
|
+
console.log("Could not trigger a step function.");
|
|
50
|
+
console.error(ex);
|
|
54
51
|
return null;
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
async fetch(task) {
|
|
58
55
|
const executionArn = task.eventResponse?.executionArn;
|
|
59
56
|
if (!executionArn) {
|
|
60
|
-
|
|
57
|
+
console.error(`Execution ARN not found in task "${task.id}".`);
|
|
61
58
|
return null;
|
|
62
59
|
}
|
|
63
60
|
try {
|
|
@@ -67,9 +64,8 @@ class StepFunctionServiceImpl {
|
|
|
67
64
|
if (!result) return null;
|
|
68
65
|
return JSON.parse(JSON.stringify(result));
|
|
69
66
|
} catch (ex) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}, "Could not get the execution details.");
|
|
67
|
+
console.log("Could not get the execution details.");
|
|
68
|
+
console.error(ex);
|
|
73
69
|
return null;
|
|
74
70
|
}
|
|
75
71
|
}
|
|
@@ -77,8 +73,7 @@ class StepFunctionServiceImpl {
|
|
|
77
73
|
const StepFunctionService = TaskService.createImplementation({
|
|
78
74
|
implementation: StepFunctionServiceImpl,
|
|
79
75
|
dependencies: [
|
|
80
|
-
TenantContext
|
|
81
|
-
Logger
|
|
76
|
+
TenantContext
|
|
82
77
|
]
|
|
83
78
|
});
|
|
84
79
|
export { StepFunctionService };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service/StepFunctionService.js","sources":["../../src/service/StepFunctionService.ts"],"sourcesContent":["import type { DescribeExecutionCommandOutput } from \"@webiny/aws-sdk/client-sfn/index.js\";\nimport {\n createStepFunctionClient,\n describeExecutionFactory,\n triggerStepFunctionFactory\n} from \"@webiny/aws-sdk/client-sfn/index.js\";\nimport type { ITaskEventInput } from \"@webiny/background-tasks/api/handler/types.js\";\nimport { generateAlphaNumericId } from \"@webiny/utils\";\nimport { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport { TaskService } from \"@webiny/background-tasks/api/domain/TaskService.js\";\nimport { TenantContext } from \"@webiny/api-core/exports/api/tenancy.js\";\
|
|
1
|
+
{"version":3,"file":"service/StepFunctionService.js","sources":["../../src/service/StepFunctionService.ts"],"sourcesContent":["import type { DescribeExecutionCommandOutput } from \"@webiny/aws-sdk/client-sfn/index.js\";\nimport {\n createStepFunctionClient,\n describeExecutionFactory,\n triggerStepFunctionFactory\n} from \"@webiny/aws-sdk/client-sfn/index.js\";\nimport type { ITaskEventInput } from \"@webiny/background-tasks/api/handler/types.js\";\nimport { generateAlphaNumericId } from \"@webiny/utils\";\nimport { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport { TaskService } from \"@webiny/background-tasks/api/domain/TaskService.js\";\nimport { TenantContext } from \"@webiny/api-core/exports/api/tenancy.js\";\n\nexport type IStepFunctionServiceFetchResult = DescribeExecutionCommandOutput;\n\nexport interface IDetailWrapper<T> {\n detail: T;\n}\n\nclass StepFunctionServiceImpl implements TaskService.Interface {\n private readonly trigger;\n private readonly get;\n\n public constructor(private readonly tenantContext: TenantContext.Interface) {\n // TODO client must be injectable at some point via some factory + cache\n const client = createStepFunctionClient();\n this.trigger = triggerStepFunctionFactory(client);\n this.get = describeExecutionFactory(client);\n }\n public async send(task: TaskService.SendTaskParams, delay: number) {\n const manifest = await ServiceDiscovery.load();\n if (!manifest) {\n console.error(\"Service manifest not found.\");\n return null;\n }\n const { bgTaskSfn } = manifest.api || {};\n if (!bgTaskSfn) {\n console.error(\"Background task state machine not found.\");\n return null;\n }\n const tenant = this.tenantContext.getTenant();\n if (!tenant) {\n console.error(\"Tenant not found.\");\n return null;\n }\n\n const input: ITaskEventInput = {\n webinyTaskId: task.id,\n webinyTaskDefinitionId: task.definitionId,\n tenant: tenant.id,\n delay\n };\n const name = `${task.definitionId}_${task.id}_${generateAlphaNumericId(10)}`;\n try {\n const result = await this.trigger<IDetailWrapper<ITaskEventInput>>({\n input: {\n detail: input\n },\n stateMachineArn: bgTaskSfn,\n name\n });\n return {\n ...result,\n name\n };\n } catch (ex) {\n console.log(\"Could not trigger a step function.\");\n console.error(ex);\n return null;\n }\n }\n\n public async fetch(task: TaskService.Task): Promise<IStepFunctionServiceFetchResult | null> {\n const executionArn = task.eventResponse?.executionArn;\n if (!executionArn) {\n console.error(`Execution ARN not found in task \"${task.id}\".`);\n return null;\n }\n try {\n const result = await this.get({\n executionArn\n });\n if (!result) {\n return null;\n }\n return JSON.parse(JSON.stringify(result));\n } catch (ex) {\n console.log(\"Could not get the execution details.\");\n console.error(ex);\n return null;\n }\n }\n}\n\nexport const StepFunctionService = TaskService.createImplementation({\n implementation: StepFunctionServiceImpl,\n dependencies: [TenantContext]\n});\n"],"names":["StepFunctionServiceImpl","tenantContext","client","createStepFunctionClient","triggerStepFunctionFactory","describeExecutionFactory","task","delay","manifest","ServiceDiscovery","console","bgTaskSfn","tenant","input","name","generateAlphaNumericId","result","ex","executionArn","JSON","StepFunctionService","TaskService","TenantContext"],"mappings":";;;;;AAkBA,MAAMA;IAIF,YAAoCC,aAAsC,CAAE;aAAxCA,aAAa,GAAbA;QAEhC,MAAMC,SAASC;QACf,IAAI,CAAC,OAAO,GAAGC,2BAA2BF;QAC1C,IAAI,CAAC,GAAG,GAAGG,yBAAyBH;IACxC;IACA,MAAa,KAAKI,IAAgC,EAAEC,KAAa,EAAE;QAC/D,MAAMC,WAAW,MAAMC,iBAAiB,IAAI;QAC5C,IAAI,CAACD,UAAU;YACXE,QAAQ,KAAK,CAAC;YACd,OAAO;QACX;QACA,MAAM,EAAEC,SAAS,EAAE,GAAGH,SAAS,GAAG,IAAI,CAAC;QACvC,IAAI,CAACG,WAAW;YACZD,QAAQ,KAAK,CAAC;YACd,OAAO;QACX;QACA,MAAME,SAAS,IAAI,CAAC,aAAa,CAAC,SAAS;QAC3C,IAAI,CAACA,QAAQ;YACTF,QAAQ,KAAK,CAAC;YACd,OAAO;QACX;QAEA,MAAMG,QAAyB;YAC3B,cAAcP,KAAK,EAAE;YACrB,wBAAwBA,KAAK,YAAY;YACzC,QAAQM,OAAO,EAAE;YACjBL;QACJ;QACA,MAAMO,OAAO,GAAGR,KAAK,YAAY,CAAC,CAAC,EAAEA,KAAK,EAAE,CAAC,CAAC,EAAES,uBAAuB,KAAK;QAC5E,IAAI;YACA,MAAMC,SAAS,MAAM,IAAI,CAAC,OAAO,CAAkC;gBAC/D,OAAO;oBACH,QAAQH;gBACZ;gBACA,iBAAiBF;gBACjBG;YACJ;YACA,OAAO;gBACH,GAAGE,MAAM;gBACTF;YACJ;QACJ,EAAE,OAAOG,IAAI;YACTP,QAAQ,GAAG,CAAC;YACZA,QAAQ,KAAK,CAACO;YACd,OAAO;QACX;IACJ;IAEA,MAAa,MAAMX,IAAsB,EAAmD;QACxF,MAAMY,eAAeZ,KAAK,aAAa,EAAE;QACzC,IAAI,CAACY,cAAc;YACfR,QAAQ,KAAK,CAAC,CAAC,iCAAiC,EAAEJ,KAAK,EAAE,CAAC,EAAE,CAAC;YAC7D,OAAO;QACX;QACA,IAAI;YACA,MAAMU,SAAS,MAAM,IAAI,CAAC,GAAG,CAAC;gBAC1BE;YACJ;YACA,IAAI,CAACF,QACD,OAAO;YAEX,OAAOG,KAAK,KAAK,CAACA,KAAK,SAAS,CAACH;QACrC,EAAE,OAAOC,IAAI;YACTP,QAAQ,GAAG,CAAC;YACZA,QAAQ,KAAK,CAACO;YACd,OAAO;QACX;IACJ;AACJ;AAEO,MAAMG,sBAAsBC,YAAY,oBAAoB,CAAC;IAChE,gBAAgBrB;IAChB,cAAc;QAACsB;KAAc;AACjC"}
|