@etohq/connector-engine 1.5.1-alpha.4 → 1.5.1-alpha.5

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @etohq/connector-engine@0.0.1 build /Users/solarsoft0/workspace/obigtech/shopabox/shopabox-platform-api/eto/packages/core/connector-engine
2
+ > @etohq/connector-engine@1.5.1-alpha.4 build /Users/solarsoft0/workspace/obigtech/shopabox/shopabox-platform-api/eto/packages/core/connector-engine
3
3
  > tsc
4
4
 
package/README.md CHANGED
@@ -1,253 +1,253 @@
1
- # ETO Framework Connector Engine
1
+ # @etohq/connector-engine
2
2
 
3
- A universal, type-safe connector engine with operation groups for orchestrating cross-domain operations.
3
+ Type-safe connector orchestration for Eto workflows.
4
4
 
5
- ## 🎯 Overview
5
+ ## Overview
6
6
 
7
- The ETO Connector Engine enables you to:
8
- - **Orchestrate operations** across multiple domains (meetings, logistics, commerce)
9
- - **Maintain full type safety** with compile-time validation
10
- - **Configure flexible behaviors** (execute all, route by domain, first success)
11
- - **Compose workflows** seamlessly with ETO framework
12
- - **Support union return types** (steps or promises) from plugins
7
+ `@etohq/connector-engine` provides:
13
8
 
14
- ## 🏗️ Architecture
9
+ - registers connector plugins with typed operations,
10
+ - auto-generates strongly typed execution methods,
11
+ - supports grouped execution with routing and fallback,
12
+ - composes directly with `@etohq/framework/workflows-sdk`.
13
+ - includes a strict runtime API with middleware and schema validation.
15
14
 
16
- ### Two-Parameter Configuration
17
- ```typescript
18
- const engine = ConnectorEngine(connectorTypes, operationGroups);
15
+ ## Core Concepts
16
+
17
+ - `ConnectorPlugin`: plugin contract (`getName`, `getVersion`, `operations`).
18
+ - `operations`: map of async handlers `(input, config) => output`.
19
+ - `ConnectorEngine(connectors, groups?, config?)`: engine factory.
20
+ - `configLoader`: runtime connector config source.
21
+ - `routingConfigLoader`: optional routing source for grouped execution.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pnpm add @etohq/connector-engine
19
27
  ```
20
28
 
21
- 1. **Connector Types**: Define domain operations with input/output types
22
- 2. **Operation Groups**: Define orchestration behavior across domains
23
-
24
- ### Auto-Generated Methods
25
- The engine generates type-safe methods like:
26
- - `executeResourceCheckAvailability()` - Route by domain
27
- - `executeInternalCheckAvailability()` - Execute all domains
28
- - `executeExternalReserveResource()` - First success behavior
29
-
30
- ## 🚀 Quick Start
31
-
32
- ### 1. Define Connector Types
33
- ```typescript
34
- const connectorTypes = {
35
- meetings: {
36
- checkAvailability: {
37
- input: { resourceType: string; timeSlot: { start: Date; end: Date } },
38
- output: { available: boolean; conflicts: any[] }
39
- }
40
- },
41
- logistics: {
42
- checkAvailability: {
43
- input: { vehicleType: string; timeSlot: { start: Date; end: Date } },
44
- output: { available: boolean; vehicles: any[] }
45
- }
29
+ ## Plugin Contract
30
+
31
+ ```ts
32
+ import {
33
+ AbstractConnectorPlugin,
34
+ type OperationType,
35
+ } from "@etohq/connector-engine"
36
+
37
+ type PaymentOps = {
38
+ createCustomer: {
39
+ input: { email: string; entity_id: string }
40
+ output: { customer_id: string; psp_customer_id: string }
46
41
  }
47
- } as const;
48
- ```
42
+ createVirtualAccount: {
43
+ input: { customer_id: string; currency: string }
44
+ output: { account_id: string; account_number: string }
45
+ }
46
+ }
49
47
 
50
- ### 2. Define Operation Groups
51
- ```typescript
52
- const operationGroups = {
53
- resource: {
54
- domains: ['meetings', 'logistics'],
55
- operations: ['checkAvailability'],
56
- options: { behavior: 'route_by_domain' }
48
+ class PaystackPlugin extends AbstractConnectorPlugin<PaymentOps> {
49
+ getName() {
50
+ return "payment"
57
51
  }
58
- } as const;
59
- ```
60
52
 
61
- ### 3. Create Engine
62
- ```typescript
63
- const engine = ConnectorEngine(connectorTypes, operationGroups);
53
+ getVersion() {
54
+ return "1.0.0"
55
+ }
56
+
57
+ operations = {
58
+ createCustomer: async (input, config) => {
59
+ return {
60
+ customer_id: "cust_123",
61
+ psp_customer_id: "CUS_abc123",
62
+ }
63
+ },
64
+ createVirtualAccount: async (input, config) => {
65
+ return {
66
+ account_id: "va_123",
67
+ account_number: "1234567890",
68
+ }
69
+ },
70
+ }
71
+ }
64
72
  ```
65
73
 
66
- ### 4. Use Type-Safe Methods
67
- ```typescript
68
- // ✅ Domain optional - uses operation group default
69
- const result = await engine.executeResourceCheckAvailability({
70
- // No domain needed - operation group routes to default domain
71
- resourceType: 'conference_room',
72
- timeSlot: { start: new Date(), end: new Date() }
73
- });
74
-
75
- // ✅ Domain override when needed
76
- const specificResult = await engine.executeResourceCheckAvailability({
77
- domain: 'logistics', // Optional override - takes precedence
78
- resourceType: 'delivery_truck',
79
- timeSlot: { start: new Date(), end: new Date() }
80
- });
74
+ ## Create Engine (Workflow-First API)
75
+
76
+ ```ts
77
+ import { ConnectorEngine } from "@etohq/connector-engine"
78
+
79
+ const engine = ConnectorEngine(
80
+ {
81
+ paystack: new PaystackPlugin(),
82
+ },
83
+ {
84
+ payment: {
85
+ connectors: ["paystack"],
86
+ operations: ["createCustomer", "createVirtualAccount"],
87
+ options: {
88
+ behavior: "route_by_domain",
89
+ },
90
+ },
91
+ },
92
+ {
93
+ configLoader: async (connectorId) => {
94
+ // Fetch connector secrets/settings from DB or vault.
95
+ return { provider: connectorId }
96
+ },
97
+ routingConfigLoader: async (groupId) => {
98
+ // Optional dynamic routing profile from DB.
99
+ return {
100
+ profile_id: "default",
101
+ name: "default",
102
+ algorithm: { type: "priority", data: [] },
103
+ created_at: new Date().toISOString(),
104
+ modified_at: new Date().toISOString(),
105
+ version: 1,
106
+ }
107
+ },
108
+ }
109
+ )
81
110
  ```
82
111
 
83
- ## 📋 Operation Group Behaviors
112
+ ## Execute Operations
84
113
 
85
- ### `route_by_domain`
86
- Routes to specific domain. Domain is optional - uses group default or input override:
87
- ```typescript
88
- {
89
- behavior: 'route_by_domain',
90
- connectorId?: 'specific-connector'
91
- }
114
+ ### Per Connector
115
+
116
+ Engine auto-generates methods from connector id + operation name:
92
117
 
93
- // Usage:
94
- await engine.executeResourceCheckAvailability({
95
- // domain optional - uses group's first domain
96
- resourceType: 'room'
97
- });
118
+ - `executePaystackCreateCustomer`
119
+ - `executePaystackCreateVirtualAccount`
98
120
 
99
- await engine.executeResourceCheckAvailability({
100
- domain: 'meetings', // Optional override
101
- resourceType: 'room'
102
- });
121
+ ```ts
122
+ const wf = engine.executePaystackCreateCustomer()
123
+ const { result } = await wf.run({
124
+ input: { entity_id: "ent_1", email: "dev@eto.dev" },
125
+ })
103
126
  ```
104
127
 
105
- ### `execute_all`
106
- Executes all domains in parallel. No domain parameter needed:
107
- ```typescript
108
- {
109
- behavior: 'execute_all',
110
- timeout: 30000,
111
- retries: 2
112
- }
128
+ ### Per Group/Domain
113
129
 
114
- // Usage:
115
- await engine.executeInternalCheckAvailability({
116
- // No domain field - executes all group domains
117
- resourceType: 'any_resource'
118
- });
119
- ```
130
+ Engine auto-generates methods from domain (`plugin.getName()`) + operation:
120
131
 
121
- ### `first_success`
122
- Executes domains until first success. No domain parameter needed:
123
- ```typescript
124
- {
125
- behavior: 'first_success',
126
- priority: 1
127
- }
132
+ - `executePaymentCreateCustomer`
133
+ - `executePaymentCreateVirtualAccount`
128
134
 
129
- // Usage:
130
- await engine.executeExternalReserveResource({
131
- // No domain field - tries domains until success
132
- resourceType: 'resource'
133
- });
135
+ ```ts
136
+ const wf = engine.executePaymentCreateCustomer(
137
+ { entity_id: "ent_1", email: "dev@eto.dev" },
138
+ { country: "NG" }
139
+ )
140
+
141
+ const { result } = await wf.run({
142
+ input: { entity_id: "ent_1", email: "dev@eto.dev" },
143
+ })
134
144
  ```
135
145
 
136
- ## 🔧 Plugin Development
146
+ ## Group Behaviors
137
147
 
138
- ### Simple Plugin (Returns Promise)
139
- ```typescript
140
- class SimplePlugin extends BaseConnectorPlugin {
141
- async checkAvailability(config, input, { container }) {
142
- const service = container.resolve(Modules.BOOKING);
143
- return await service.findAvailability(input);
144
- }
145
- }
146
- ```
148
+ `options.behavior` supports:
149
+
150
+ - `route_by_domain`: use routing config + fallback connectors.
151
+ - `execute_all`: execute all connectors in the group.
152
+ - `first_success`: try connectors until first success.
153
+
154
+ ## Integration in Eto Workflows
155
+
156
+ Use generated connector workflows inside regular Eto workflows:
157
+
158
+ ```ts
159
+ import { createWorkflow, WorkflowResponse } from "@etohq/framework/workflows-sdk"
147
160
 
148
- ### Advanced Plugin (Returns Step)
149
- ```typescript
150
- class AdvancedPlugin extends BaseConnectorPlugin {
151
- checkAvailability(config, input, { container }) {
152
- return createStep("advanced-check", async (stepInput, { container }) => {
153
- // Complex logic with compensation
154
- const result = await this.complexCheck(stepInput, container);
155
- return new StepResponse(result);
156
- });
161
+ export const createCustomerWorkflow = createWorkflow(
162
+ "create-customer",
163
+ (input) => {
164
+ const customer = engine.executePaymentCreateCustomer(
165
+ { entity_id: input.entity_id, email: input.email },
166
+ { country: input.country }
167
+ )(input)
168
+
169
+ return new WorkflowResponse(customer)
157
170
  }
158
- }
171
+ )
159
172
  ```
160
173
 
161
- ## 📊 Type Safety Features
174
+ ## Runtime Notes
162
175
 
163
- ### Input Type Inference
164
- - **route_by_domain**: Union of domain inputs + domain field
165
- - **execute_all**: Intersection of all domain inputs
176
+ - The engine itself has no built-in database.
177
+ - DB-backed behavior is provided by your `configLoader` and `routingConfigLoader`.
178
+ - Keep provider secrets outside code; load at runtime.
166
179
 
167
- ### Output Type Inference
168
- - **route_by_domain**: Single domain output
169
- - **execute_all**: OperationGroupResult with all domain results
180
+ ## Runtime API (Single Primitive)
170
181
 
171
- ### Compile-Time Validation
172
- - Domain names are type-checked
173
- - Operation names are validated
174
- - Input/output types are enforced
182
+ Use `createRuntimeConnectorEngine` when you want one canonical primitive:
183
+ `execute({ domain, operation, input, ... })`.
175
184
 
176
- ## 🎨 Advanced Examples
185
+ ```ts
186
+ import {
187
+ createRuntimeConnectorEngine,
188
+ type ConnectorExecuteRequest,
189
+ } from "@etohq/connector-engine"
177
190
 
178
- See `/examples/booking-example.ts` for comprehensive usage examples including:
179
- - Multi-domain resource allocation
180
- - Cross-domain notifications
181
- - Priority-based execution
182
- - Error handling and retries
191
+ const runtime = createRuntimeConnectorEngine({
192
+ configLoader: async (connectorId) => ({ provider: connectorId }),
193
+ })
183
194
 
184
- ## 🧪 Testing
195
+ runtime.register("paystack", new PaystackPlugin())
185
196
 
186
- Run the test suite:
187
- ```bash
188
- npm test
189
- # or
190
- node examples/booking-test.ts
197
+ const result = await runtime.execute({
198
+ domain: "payment",
199
+ operation: "createCustomer",
200
+ input: { entity_id: "ent_1", email: "dev@eto.dev" },
201
+ })
191
202
  ```
192
203
 
193
- ## 📚 API Reference
204
+ ### Schema Protocol (Any Schema Library)
194
205
 
195
- ### ConnectorEngine Factory
196
- ```typescript
197
- function ConnectorEngine<TConnectorTypes, TOperationGroups>(
198
- connectorTypes: TConnectorTypes,
199
- operationGroups?: TOperationGroups
200
- ): ConnectorEngineImpl
201
- ```
206
+ `execute` accepts `inputSchema` and `outputSchema` using a schema protocol:
202
207
 
203
- ### Operation Group Configuration
204
- ```typescript
205
- interface OperationGroupsConfig {
206
- [groupName: string]: {
207
- domains: string[];
208
- operations: string[];
209
- options: {
210
- behavior: 'execute_all' | 'route_by_domain' | 'first_success';
211
- connectorId?: string;
212
- priority?: number;
213
- timeout?: number;
214
- retries?: number;
215
- };
216
- };
217
- }
208
+ - `parse(input) => value`, or
209
+ - `safeParse(input) => { success, data | error }`
210
+
211
+ ```ts
212
+ const result = await runtime.execute({
213
+ domain: "payment",
214
+ operation: "createCustomer",
215
+ input: payload,
216
+ inputSchema: customerInputSchema, // zod/valibot/custom adapter
217
+ outputSchema: customerOutputSchema,
218
+ })
218
219
  ```
219
220
 
220
- ## 🔗 Integration with ETO Framework
221
+ When schemas are provided, `execute` infers input/output types from them automatically.
221
222
 
222
- The connector engine seamlessly integrates with ETO workflows:
223
+ You can also pre-register schemas per connector operation:
223
224
 
224
- ```typescript
225
- const workflow = createWorkflow("booking", async (input) => {
226
- const availability = await engine.executeResourceCheckAvailability({
227
- domain: 'meetings',
228
- resourceType: input.resourceType,
229
- timeSlot: input.timeSlot
230
- }).runAsStep({ input });
231
-
232
- return new WorkflowResponse(availability);
233
- });
225
+ ```ts
226
+ runtime.registerOperationSchemas("paystack", "createCustomer", {
227
+ inputSchema: customerInputSchema,
228
+ outputSchema: customerOutputSchema,
229
+ })
234
230
  ```
235
231
 
236
- ## 🎯 Use Cases
237
-
238
- - **Resource Booking Systems**: Meetings, rooms, equipment
239
- - **Logistics Management**: Vehicle scheduling, route optimization
240
- - **E-commerce Operations**: Inventory, fulfillment, payments
241
- - **Multi-tenant Applications**: Domain-specific operations
242
- - **Microservices Orchestration**: Cross-service coordination
243
-
244
- ## 🤝 Contributing
232
+ ### Middleware
245
233
 
246
- 1. Follow ETO framework patterns
247
- 2. Maintain full type safety
248
- 3. Add comprehensive tests
249
- 4. Update documentation
234
+ ```ts
235
+ runtime.use({
236
+ name: "trace",
237
+ run: async (req, next) => {
238
+ const started = Date.now()
239
+ const result = await next()
240
+ console.log(req.operation, Date.now() - started)
241
+ return result
242
+ },
243
+ })
244
+ ```
250
245
 
251
- ## 📄 License
246
+ ## Troubleshooting
252
247
 
253
- Part of the ETO Framework ecosystem.
248
+ - Missing generated method:
249
+ check connector id/domain name and operation key spelling.
250
+ - Operation not found on connector:
251
+ ensure plugin exposes it under `operations`.
252
+ - Group routing errors:
253
+ validate `routingConfigLoader` output shape and connector ids.
@@ -3,5 +3,7 @@
3
3
  * @description Clean plugin-first connector engine
4
4
  */
5
5
  export { ConnectorEngine } from "./clean-connector-engine";
6
+ export { RuntimeConnectorEngine, createRuntimeConnectorEngine, } from "./runtime-engine";
6
7
  export type { ConnectorRegistry, OperationGroup, OperationGroups, EngineConfig, GroupResult } from "./clean-connector-engine";
8
+ export type { RuntimeEngineConfig } from "./runtime-engine";
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,EACZ,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -4,7 +4,10 @@
4
4
  * @description Clean plugin-first connector engine
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ConnectorEngine = void 0;
7
+ exports.createRuntimeConnectorEngine = exports.RuntimeConnectorEngine = exports.ConnectorEngine = void 0;
8
8
  var clean_connector_engine_1 = require("./clean-connector-engine");
9
9
  Object.defineProperty(exports, "ConnectorEngine", { enumerable: true, get: function () { return clean_connector_engine_1.ConnectorEngine; } });
10
+ var runtime_engine_1 = require("./runtime-engine");
11
+ Object.defineProperty(exports, "RuntimeConnectorEngine", { enumerable: true, get: function () { return runtime_engine_1.RuntimeConnectorEngine; } });
12
+ Object.defineProperty(exports, "createRuntimeConnectorEngine", { enumerable: true, get: function () { return runtime_engine_1.createRuntimeConnectorEngine; } });
10
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mEAA2D;AAAlD,yHAAA,eAAe,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mEAA2D;AAAlD,yHAAA,eAAe,OAAA;AACxB,mDAG0B;AAFxB,wHAAA,sBAAsB,OAAA;AACtB,8HAAA,4BAA4B,OAAA"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Runtime connector engine with middleware and schema protocol support.
3
+ */
4
+ import { ConnectorPlugin } from "../types/connector-plugin";
5
+ import { ConnectorExecuteRequest, ConnectorExecuteResult, ConnectorMiddleware, ConnectorOperationSchemas, InferSchemaOutput, SchemaProtocol } from "../types/runtime";
6
+ export interface RuntimeEngineConfig {
7
+ configLoader?: (connectorId: string) => Promise<unknown>;
8
+ }
9
+ export declare class RuntimeConnectorEngine {
10
+ private connectors;
11
+ private middleware;
12
+ private configLoader;
13
+ private operationSchemas;
14
+ constructor(config?: RuntimeEngineConfig);
15
+ register(connectorId: string, plugin: ConnectorPlugin): this;
16
+ registerMany(connectors: Record<string, ConnectorPlugin>): this;
17
+ use(middleware: ConnectorMiddleware): this;
18
+ registerOperationSchemas<TInput, TOutput>(connectorId: string, operation: string, schemas: ConnectorOperationSchemas<TInput, TOutput>): this;
19
+ execute<TInputSchema extends SchemaProtocol<unknown> | undefined = undefined, TOutputSchema extends SchemaProtocol<unknown> | undefined = undefined, TInput = TInputSchema extends SchemaProtocol<unknown> ? InferSchemaOutput<TInputSchema> : unknown, TOutput = TOutputSchema extends SchemaProtocol<unknown> ? InferSchemaOutput<TOutputSchema> : unknown>(request: ConnectorExecuteRequest<TInput, TOutput> & {
20
+ inputSchema?: TInputSchema;
21
+ outputSchema?: TOutputSchema;
22
+ }): Promise<ConnectorExecuteResult<TOutput>>;
23
+ executeGroup<TInputSchema extends SchemaProtocol<unknown> | undefined = undefined, TOutputSchema extends SchemaProtocol<unknown> | undefined = undefined, TInput = TInputSchema extends SchemaProtocol<unknown> ? InferSchemaOutput<TInputSchema> : unknown, TOutput = TOutputSchema extends SchemaProtocol<unknown> ? InferSchemaOutput<TOutputSchema> : unknown>(request: Omit<ConnectorExecuteRequest<TInput, TOutput>, "connectorId"> & {
24
+ inputSchema?: TInputSchema;
25
+ outputSchema?: TOutputSchema;
26
+ }): Promise<ConnectorExecuteResult<TOutput>[]>;
27
+ private executeWithFallback;
28
+ private executeOnConnector;
29
+ private resolveSchemas;
30
+ private applySchema;
31
+ private selectConnectors;
32
+ private createErrorResult;
33
+ private makeRequestId;
34
+ }
35
+ export declare function createRuntimeConnectorEngine(config?: RuntimeEngineConfig): RuntimeConnectorEngine;
36
+ //# sourceMappingURL=runtime-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-engine.d.ts","sourceRoot":"","sources":["../../src/engine/runtime-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACf,MAAM,kBAAkB,CAAA;AAEzB,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD;AAKD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,gBAAgB,CAAoC;gBAEhD,MAAM,CAAC,EAAE,mBAAmB;IAIxC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IAK5D,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI;IAO/D,GAAG,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAK1C,wBAAwB,CAAC,MAAM,EAAE,OAAO,EACtC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,yBAAyB,CAAC,MAAM,EAAE,OAAO,CAAC,GAClD,IAAI;IAUD,OAAO,CACX,YAAY,SAAS,cAAc,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,EACpE,aAAa,SAAS,cAAc,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,EACrE,MAAM,GAAG,YAAY,SAAS,cAAc,CAAC,OAAO,CAAC,GACjD,iBAAiB,CAAC,YAAY,CAAC,GAC/B,OAAO,EACX,OAAO,GAAG,aAAa,SAAS,cAAc,CAAC,OAAO,CAAC,GACnD,iBAAiB,CAAC,aAAa,CAAC,GAChC,OAAO,EAEX,OAAO,EAAE,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAClD,WAAW,CAAC,EAAE,YAAY,CAAA;QAC1B,YAAY,CAAC,EAAE,aAAa,CAAA;KAC7B,GACA,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAkBrC,YAAY,CAChB,YAAY,SAAS,cAAc,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,EACpE,aAAa,SAAS,cAAc,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,EACrE,MAAM,GAAG,YAAY,SAAS,cAAc,CAAC,OAAO,CAAC,GACjD,iBAAiB,CAAC,YAAY,CAAC,GAC/B,OAAO,EACX,OAAO,GAAG,aAAa,SAAS,cAAc,CAAC,OAAO,CAAC,GACnD,iBAAiB,CAAC,aAAa,CAAC,GAChC,OAAO,EAEX,OAAO,EAAE,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,GAAG;QACvE,WAAW,CAAC,EAAE,YAAY,CAAA;QAC1B,YAAY,CAAC,EAAE,aAAa,CAAA;KAC7B,GACA,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;YAiC/B,mBAAmB;YAsDnB,kBAAkB;IA4EhC,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,gBAAgB;IAwBxB,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,aAAa;CAGtB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,CAAC,EAAE,mBAAmB,GAC3B,sBAAsB,CAExB"}