@versori/run 0.2.13 → 0.2.15

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.
Files changed (153) hide show
  1. package/esm/src/context/AsyncWorkflow.d.ts +14 -0
  2. package/esm/src/context/AsyncWorkflow.d.ts.map +1 -0
  3. package/esm/src/context/AsyncWorkflow.js +89 -0
  4. package/esm/src/context/Context.d.ts +12 -1
  5. package/esm/src/context/Context.d.ts.map +1 -1
  6. package/esm/src/context/Context.js +43 -4
  7. package/esm/src/context/ContextProvider.d.ts +3 -1
  8. package/esm/src/context/ContextProvider.d.ts.map +1 -1
  9. package/esm/src/context/ContextProvider.js +9 -2
  10. package/esm/src/dsl/http/versori/constants.d.ts +1 -0
  11. package/esm/src/dsl/http/versori/constants.d.ts.map +1 -1
  12. package/esm/src/dsl/http/versori/constants.js +1 -0
  13. package/esm/src/dsl/triggers/DurableTrigger.d.ts +17 -0
  14. package/esm/src/dsl/triggers/DurableTrigger.d.ts.map +1 -0
  15. package/esm/src/dsl/triggers/DurableTrigger.js +36 -0
  16. package/esm/src/dsl/triggers/mod.d.ts +1 -0
  17. package/esm/src/dsl/triggers/mod.d.ts.map +1 -1
  18. package/esm/src/dsl/triggers/mod.js +1 -0
  19. package/esm/src/interpreter/durable/DurableInterpreter.d.ts +52 -0
  20. package/esm/src/interpreter/durable/DurableInterpreter.d.ts.map +1 -0
  21. package/esm/src/interpreter/durable/DurableInterpreter.js +433 -0
  22. package/esm/src/interpreter/durable/ExecutionError.d.ts +6 -0
  23. package/esm/src/interpreter/durable/ExecutionError.d.ts.map +1 -0
  24. package/esm/src/interpreter/durable/ExecutionError.js +13 -0
  25. package/esm/src/interpreter/durable/ObservableCompiler.d.ts +35 -0
  26. package/esm/src/interpreter/durable/ObservableCompiler.d.ts.map +1 -0
  27. package/esm/src/interpreter/durable/ObservableCompiler.js +69 -0
  28. package/esm/src/interpreter/durable/Queue.d.ts +60 -0
  29. package/esm/src/interpreter/durable/Queue.d.ts.map +1 -0
  30. package/esm/src/interpreter/durable/Queue.js +131 -0
  31. package/esm/src/interpreter/durable/compilers/background.d.ts +4 -0
  32. package/esm/src/interpreter/durable/compilers/background.d.ts.map +1 -0
  33. package/esm/src/interpreter/durable/compilers/background.js +22 -0
  34. package/esm/src/interpreter/durable/compilers/catch.d.ts +4 -0
  35. package/esm/src/interpreter/durable/compilers/catch.d.ts.map +1 -0
  36. package/esm/src/interpreter/durable/compilers/catch.js +36 -0
  37. package/esm/src/interpreter/durable/compilers/chain.d.ts +3 -0
  38. package/esm/src/interpreter/durable/compilers/chain.d.ts.map +1 -0
  39. package/esm/src/interpreter/durable/compilers/chain.js +9 -0
  40. package/esm/src/interpreter/durable/compilers/durableworkflow.d.ts +8 -0
  41. package/esm/src/interpreter/durable/compilers/durableworkflow.d.ts.map +1 -0
  42. package/esm/src/interpreter/durable/compilers/durableworkflow.js +54 -0
  43. package/esm/src/interpreter/durable/compilers/fn.d.ts +4 -0
  44. package/esm/src/interpreter/durable/compilers/fn.d.ts.map +1 -0
  45. package/esm/src/interpreter/durable/compilers/fn.js +22 -0
  46. package/esm/src/interpreter/durable/compilers/http.d.ts +4 -0
  47. package/esm/src/interpreter/durable/compilers/http.d.ts.map +1 -0
  48. package/esm/src/interpreter/durable/compilers/http.js +44 -0
  49. package/esm/src/interpreter/durable/compilers/mod.d.ts +2 -0
  50. package/esm/src/interpreter/durable/compilers/mod.d.ts.map +1 -0
  51. package/esm/src/interpreter/durable/compilers/mod.js +1 -0
  52. package/esm/src/interpreter/durable/compilers/parallel.d.ts +4 -0
  53. package/esm/src/interpreter/durable/compilers/parallel.d.ts.map +1 -0
  54. package/esm/src/interpreter/durable/compilers/parallel.js +19 -0
  55. package/esm/src/interpreter/durable/compilers/schedule.d.ts +4 -0
  56. package/esm/src/interpreter/durable/compilers/schedule.d.ts.map +1 -0
  57. package/esm/src/interpreter/durable/compilers/schedule.js +94 -0
  58. package/esm/src/interpreter/durable/compilers/serial.d.ts +4 -0
  59. package/esm/src/interpreter/durable/compilers/serial.d.ts.map +1 -0
  60. package/esm/src/interpreter/durable/compilers/serial.js +16 -0
  61. package/esm/src/interpreter/durable/compilers/types.d.ts +15 -0
  62. package/esm/src/interpreter/durable/compilers/types.d.ts.map +1 -0
  63. package/esm/src/interpreter/durable/compilers/types.js +1 -0
  64. package/esm/src/interpreter/durable/compilers/unpack.d.ts +4 -0
  65. package/esm/src/interpreter/durable/compilers/unpack.d.ts.map +1 -0
  66. package/esm/src/interpreter/durable/compilers/unpack.js +22 -0
  67. package/esm/src/interpreter/durable/compilers/webhook.d.ts +4 -0
  68. package/esm/src/interpreter/durable/compilers/webhook.d.ts.map +1 -0
  69. package/esm/src/interpreter/durable/compilers/webhook.js +248 -0
  70. package/esm/src/interpreter/durable/mod.d.ts +5 -0
  71. package/esm/src/interpreter/durable/mod.d.ts.map +1 -0
  72. package/esm/src/interpreter/durable/mod.js +4 -0
  73. package/esm/src/interpreter/memory/MemoryInterpreter.js +1 -1
  74. package/esm/src/interpreter/mod.d.ts +1 -0
  75. package/esm/src/interpreter/mod.d.ts.map +1 -1
  76. package/esm/src/interpreter/mod.js +1 -0
  77. package/package.json +1 -1
  78. package/script/src/context/AsyncWorkflow.d.ts +14 -0
  79. package/script/src/context/AsyncWorkflow.d.ts.map +1 -0
  80. package/script/src/context/AsyncWorkflow.js +93 -0
  81. package/script/src/context/Context.d.ts +12 -1
  82. package/script/src/context/Context.d.ts.map +1 -1
  83. package/script/src/context/Context.js +43 -4
  84. package/script/src/context/ContextProvider.d.ts +3 -1
  85. package/script/src/context/ContextProvider.d.ts.map +1 -1
  86. package/script/src/context/ContextProvider.js +9 -2
  87. package/script/src/dsl/http/versori/constants.d.ts +1 -0
  88. package/script/src/dsl/http/versori/constants.d.ts.map +1 -1
  89. package/script/src/dsl/http/versori/constants.js +2 -1
  90. package/script/src/dsl/triggers/DurableTrigger.d.ts +17 -0
  91. package/script/src/dsl/triggers/DurableTrigger.d.ts.map +1 -0
  92. package/script/src/dsl/triggers/DurableTrigger.js +41 -0
  93. package/script/src/dsl/triggers/mod.d.ts +1 -0
  94. package/script/src/dsl/triggers/mod.d.ts.map +1 -1
  95. package/script/src/dsl/triggers/mod.js +3 -1
  96. package/script/src/interpreter/durable/DurableInterpreter.d.ts +52 -0
  97. package/script/src/interpreter/durable/DurableInterpreter.d.ts.map +1 -0
  98. package/script/src/interpreter/durable/DurableInterpreter.js +440 -0
  99. package/script/src/interpreter/durable/ExecutionError.d.ts +6 -0
  100. package/script/src/interpreter/durable/ExecutionError.d.ts.map +1 -0
  101. package/script/src/interpreter/durable/ExecutionError.js +17 -0
  102. package/script/src/interpreter/durable/ObservableCompiler.d.ts +35 -0
  103. package/script/src/interpreter/durable/ObservableCompiler.d.ts.map +1 -0
  104. package/script/src/interpreter/durable/ObservableCompiler.js +73 -0
  105. package/script/src/interpreter/durable/Queue.d.ts +60 -0
  106. package/script/src/interpreter/durable/Queue.d.ts.map +1 -0
  107. package/script/src/interpreter/durable/Queue.js +135 -0
  108. package/script/src/interpreter/durable/compilers/background.d.ts +4 -0
  109. package/script/src/interpreter/durable/compilers/background.d.ts.map +1 -0
  110. package/script/src/interpreter/durable/compilers/background.js +25 -0
  111. package/script/src/interpreter/durable/compilers/catch.d.ts +4 -0
  112. package/script/src/interpreter/durable/compilers/catch.d.ts.map +1 -0
  113. package/script/src/interpreter/durable/compilers/catch.js +39 -0
  114. package/script/src/interpreter/durable/compilers/chain.d.ts +3 -0
  115. package/script/src/interpreter/durable/compilers/chain.d.ts.map +1 -0
  116. package/script/src/interpreter/durable/compilers/chain.js +12 -0
  117. package/script/src/interpreter/durable/compilers/durableworkflow.d.ts +8 -0
  118. package/script/src/interpreter/durable/compilers/durableworkflow.d.ts.map +1 -0
  119. package/script/src/interpreter/durable/compilers/durableworkflow.js +58 -0
  120. package/script/src/interpreter/durable/compilers/fn.d.ts +4 -0
  121. package/script/src/interpreter/durable/compilers/fn.d.ts.map +1 -0
  122. package/script/src/interpreter/durable/compilers/fn.js +25 -0
  123. package/script/src/interpreter/durable/compilers/http.d.ts +4 -0
  124. package/script/src/interpreter/durable/compilers/http.d.ts.map +1 -0
  125. package/script/src/interpreter/durable/compilers/http.js +47 -0
  126. package/script/src/interpreter/durable/compilers/mod.d.ts +2 -0
  127. package/script/src/interpreter/durable/compilers/mod.d.ts.map +1 -0
  128. package/script/src/interpreter/durable/compilers/mod.js +2 -0
  129. package/script/src/interpreter/durable/compilers/parallel.d.ts +4 -0
  130. package/script/src/interpreter/durable/compilers/parallel.d.ts.map +1 -0
  131. package/script/src/interpreter/durable/compilers/parallel.js +22 -0
  132. package/script/src/interpreter/durable/compilers/schedule.d.ts +4 -0
  133. package/script/src/interpreter/durable/compilers/schedule.d.ts.map +1 -0
  134. package/script/src/interpreter/durable/compilers/schedule.js +97 -0
  135. package/script/src/interpreter/durable/compilers/serial.d.ts +4 -0
  136. package/script/src/interpreter/durable/compilers/serial.d.ts.map +1 -0
  137. package/script/src/interpreter/durable/compilers/serial.js +19 -0
  138. package/script/src/interpreter/durable/compilers/types.d.ts +15 -0
  139. package/script/src/interpreter/durable/compilers/types.d.ts.map +1 -0
  140. package/script/src/interpreter/durable/compilers/types.js +2 -0
  141. package/script/src/interpreter/durable/compilers/unpack.d.ts +4 -0
  142. package/script/src/interpreter/durable/compilers/unpack.d.ts.map +1 -0
  143. package/script/src/interpreter/durable/compilers/unpack.js +25 -0
  144. package/script/src/interpreter/durable/compilers/webhook.d.ts +4 -0
  145. package/script/src/interpreter/durable/compilers/webhook.d.ts.map +1 -0
  146. package/script/src/interpreter/durable/compilers/webhook.js +254 -0
  147. package/script/src/interpreter/durable/mod.d.ts +5 -0
  148. package/script/src/interpreter/durable/mod.d.ts.map +1 -0
  149. package/script/src/interpreter/durable/mod.js +20 -0
  150. package/script/src/interpreter/memory/MemoryInterpreter.js +1 -1
  151. package/script/src/interpreter/mod.d.ts +1 -0
  152. package/script/src/interpreter/mod.d.ts.map +1 -1
  153. package/script/src/interpreter/mod.js +14 -0
@@ -0,0 +1,433 @@
1
+ import opentelemetry from '@opentelemetry/api';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
3
+ import { resourceFromAttributes } from '@opentelemetry/resources';
4
+ import { NodeSDK } from '@opentelemetry/sdk-node';
5
+ import express from 'express';
6
+ import xmlparser from 'express-xml-bodyparser';
7
+ import { catchError, EMPTY, mergeMap, of, tap } from 'rxjs';
8
+ import { ContextProviderImpl } from '../../context/ContextProvider.js';
9
+ import { DefaultRoundTripperFactory } from '../../dsl/http/default.js';
10
+ import { envVarEnvId, envVarEnvironmentName, envVarLocalRun, envVarOrgId, envVarOrgSlug, envVarOtelTracesURL, envVarProjectId, envVarVersion, } from '../../dsl/http/versori/constants.js';
11
+ import { CronAPIClient } from '../../dsl/http/versori/cronapi.js';
12
+ import { PlatformAPIClient } from '../../dsl/http/versori/platformapi.js';
13
+ import { VersoriCredentialsFactory } from '../../dsl/http/versori/roundtripper.js';
14
+ import { WorkflowImpl } from '../../dsl/Workflow.js';
15
+ import { MemoryKeyValueProvider } from '../../kv/memory/MemoryKeyValueProvider.js';
16
+ import { NatsKeyValueProvider } from '../../kv/nats/NatsKeyValueProvider.js';
17
+ import { ConsoleLogger } from '../../observability/logging/ConsoleLogger.js';
18
+ import { ObservableCompiler } from './ObservableCompiler.js';
19
+ import { ProxyRoundTripper } from '../../dsl/http/versori/proxyroundtripper.js';
20
+ import { VersoriConfigReader } from '../../dsl/http/versori/configloader.js';
21
+ import { QueueImpl } from './Queue.js';
22
+ function getKVProvider(runLocal) {
23
+ if (runLocal) {
24
+ return Promise.resolve(new MemoryKeyValueProvider());
25
+ }
26
+ return NatsKeyValueProvider.fromEnv();
27
+ }
28
+ function getRoundTripperFactory(log, tracer, opts) {
29
+ if (opts && opts.runLocal) {
30
+ log.info('Running in local mode, using ProxyRoundTripperFactory');
31
+ return ProxyRoundTripper.fromEnv(log);
32
+ }
33
+ if (!opts || !opts.skipVersoriCredentials) {
34
+ return VersoriCredentialsFactory.fromEnv(log, tracer);
35
+ }
36
+ log.info('Running with default round tripper factory');
37
+ return new DefaultRoundTripperFactory();
38
+ }
39
+ export class DurableInterpreter {
40
+ constructor(log, compiler, contextProvider, roundTripperFactory, webhookRouter, cronRouter, cronRegistry, connectionProvider, cronProvider, tracer, cfgReader, queueProvider, otelSDK) {
41
+ Object.defineProperty(this, "log", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: log
46
+ });
47
+ Object.defineProperty(this, "compiler", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: compiler
52
+ });
53
+ Object.defineProperty(this, "contextProvider", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: contextProvider
58
+ });
59
+ Object.defineProperty(this, "roundTripperFactory", {
60
+ enumerable: true,
61
+ configurable: true,
62
+ writable: true,
63
+ value: roundTripperFactory
64
+ });
65
+ Object.defineProperty(this, "webhookRouter", {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: true,
69
+ value: webhookRouter
70
+ });
71
+ Object.defineProperty(this, "cronRouter", {
72
+ enumerable: true,
73
+ configurable: true,
74
+ writable: true,
75
+ value: cronRouter
76
+ });
77
+ Object.defineProperty(this, "cronRegistry", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: cronRegistry
82
+ });
83
+ Object.defineProperty(this, "connectionProvider", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: connectionProvider
88
+ });
89
+ Object.defineProperty(this, "cronProvider", {
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true,
93
+ value: cronProvider
94
+ });
95
+ Object.defineProperty(this, "tracer", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: tracer
100
+ });
101
+ Object.defineProperty(this, "cfgReader", {
102
+ enumerable: true,
103
+ configurable: true,
104
+ writable: true,
105
+ value: cfgReader
106
+ });
107
+ Object.defineProperty(this, "queueProvider", {
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ value: queueProvider
112
+ });
113
+ Object.defineProperty(this, "otelSDK", {
114
+ enumerable: true,
115
+ configurable: true,
116
+ writable: true,
117
+ value: otelSDK
118
+ });
119
+ Object.defineProperty(this, "registeredWorkflows", {
120
+ enumerable: true,
121
+ configurable: true,
122
+ writable: true,
123
+ value: []
124
+ });
125
+ Object.defineProperty(this, "webhookServer", {
126
+ enumerable: true,
127
+ configurable: true,
128
+ writable: true,
129
+ value: void 0
130
+ });
131
+ Object.defineProperty(this, "cronServer", {
132
+ enumerable: true,
133
+ configurable: true,
134
+ writable: true,
135
+ value: void 0
136
+ });
137
+ Object.defineProperty(this, "shutdownServer", {
138
+ enumerable: true,
139
+ configurable: true,
140
+ writable: true,
141
+ value: void 0
142
+ });
143
+ Object.defineProperty(this, "isShuttingDown", {
144
+ enumerable: true,
145
+ configurable: true,
146
+ writable: true,
147
+ value: false
148
+ });
149
+ if (typeof this.log === 'undefined') {
150
+ // this captures the old way of instantiating the DurableInterpreter and provides an
151
+ // error message back to the user to let them know they should use the new way.
152
+ throw new Error('DurableInterpreter should not be instantiated directly. Use DurableInterpreter.newInstance() instead.');
153
+ }
154
+ }
155
+ static async newInstance(options = {}) {
156
+ const log = options.logger || new ConsoleLogger('debug');
157
+ const compiler = options.compiler || new ObservableCompiler();
158
+ const serviceName = Deno.env.get(envVarProjectId) || 'example-service';
159
+ const environmentID = Deno.env.get(envVarEnvId) || 'development';
160
+ const version = Deno.env.get(envVarVersion) || '1.0.0';
161
+ const environment = Deno.env.get(envVarEnvironmentName) || 'development';
162
+ const orgId = Deno.env.get(envVarOrgId) || 'development';
163
+ const orgSlug = Deno.env.get(envVarOrgSlug) || 'development';
164
+ const otelTracesURL = Deno.env.get(envVarOtelTracesURL);
165
+ let otelSDK;
166
+ const configReader = VersoriConfigReader.fromEnv(log);
167
+ const runLocal = Deno.env.get(envVarLocalRun) === 'true';
168
+ await waitForReady(log);
169
+ // Do NOT change those attributes, they are used by the API to filter on
170
+ const resource = resourceFromAttributes({
171
+ 'service.id': serviceName,
172
+ 'service.environment': environment,
173
+ 'service.environment_id': environmentID,
174
+ 'service.version': version,
175
+ 'service.organisation_id': orgId,
176
+ 'service.organisation_slug': orgSlug,
177
+ });
178
+ if (otelTracesURL && serviceName) {
179
+ otelSDK = new NodeSDK({
180
+ traceExporter: new OTLPTraceExporter({
181
+ url: otelTracesURL,
182
+ }),
183
+ serviceName: serviceName,
184
+ resource: resource,
185
+ });
186
+ log.info('Starting OpenTelemetry SDK');
187
+ otelSDK.start();
188
+ }
189
+ const tracer = opentelemetry.trace.getTracer(serviceName, version);
190
+ const roundTripperFactory = getRoundTripperFactory(log, tracer, {
191
+ skipVersoriCredentials: options.skipVersoriCredentials,
192
+ runLocal: runLocal,
193
+ });
194
+ const queueProvider = await QueueImpl.fromEnv(log);
195
+ if (options.contextProvider) {
196
+ // no need to set up a key-value provider if options.contextProvider is already
197
+ // initialised.
198
+ return new DurableInterpreter(log, compiler, options.contextProvider, roundTripperFactory, express.Router(), express.Router(), new Map(), PlatformAPIClient.fromEnv(), CronAPIClient.fromEnv(), tracer, configReader, queueProvider, otelSDK);
199
+ }
200
+ const kvp = await getKVProvider(runLocal);
201
+ return new DurableInterpreter(log, compiler, new ContextProviderImpl(log, kvp, roundTripperFactory.credentials(), queueProvider), roundTripperFactory, express.Router(), express.Router(), new Map(), PlatformAPIClient.fromEnv(), CronAPIClient.fromEnv(), tracer, configReader, queueProvider, otelSDK);
202
+ }
203
+ register(workflow, options) {
204
+ const localAbortController = new AbortController();
205
+ const combinedSignal = options?.signal
206
+ ? AbortSignal.any([localAbortController.signal, options.signal])
207
+ : localAbortController.signal;
208
+ if (!(workflow instanceof WorkflowImpl)) {
209
+ throw new Error('workflow is not an instance of WorkflowImpl');
210
+ }
211
+ this.log.info('DurableInterpreter.register', { workflow });
212
+ const compilerContext = {
213
+ compiler: this.compiler,
214
+ log: this.log,
215
+ tracer: this.tracer,
216
+ contextProvider: this.contextProvider,
217
+ roundTripperFactory: this.roundTripperFactory,
218
+ webhookRouter: this.webhookRouter,
219
+ queueProvider: this.queueProvider,
220
+ cronRouter: this.cronRouter,
221
+ cronRegistry: this.cronRegistry,
222
+ connectionProvider: this.connectionProvider,
223
+ configReader: this.cfgReader,
224
+ };
225
+ const trigger$ = this.compiler.compileTrigger(compilerContext, workflow.trigger, combinedSignal);
226
+ const task$ = this.compiler.compileTask(compilerContext, workflow.task);
227
+ const registration = {
228
+ trigger$,
229
+ task$,
230
+ localAbortController,
231
+ sigintListener: () => {
232
+ this.log.info('Received SIGINT, shutting down workflow');
233
+ localAbortController.abort();
234
+ },
235
+ };
236
+ this.registeredWorkflows.push(registration);
237
+ return registration;
238
+ }
239
+ async start() {
240
+ const port = Deno.env.get('PORT') || 3000;
241
+ const cronPort = Deno.env.get('CRON_PORT') || 3001;
242
+ const webhookApp = express();
243
+ webhookApp.use(express.json({ limit: '50mb' })); // Add JSON body parser middleware
244
+ const cronApp = express();
245
+ cronApp.use(express.json());
246
+ const xml2jsDefaults = {
247
+ explicitArray: false,
248
+ normalize: false,
249
+ normalizeTags: false,
250
+ trim: true,
251
+ };
252
+ webhookApp.use(xmlparser(xml2jsDefaults));
253
+ // Add health check route
254
+ this.webhookRouter.get('/health', (_req, res) => {
255
+ res.json({ status: 'healthy' });
256
+ });
257
+ this.cronRouter.get('/health', (_req, res) => {
258
+ res.json({ status: 'healthy' });
259
+ });
260
+ // Add router to the webhookApplication
261
+ webhookApp.use(this.webhookRouter);
262
+ cronApp.use(this.cronRouter);
263
+ // Start all registered workflows
264
+ for (const registration of this.registeredWorkflows) {
265
+ Deno.addSignalListener('SIGINT', registration.sigintListener);
266
+ registration.subscription = registration.trigger$
267
+ .pipe(tap((ctx) => {
268
+ ctx.log.info('DurableInterpreter.executionStarted', { data: ctx.data });
269
+ }), mergeMap((ctx) => of(ctx).pipe(registration.task$, catchError((err) => {
270
+ ctx.log.error('DurableInterpreter.executionError', {
271
+ error: err instanceof Error ? err.toString() : err,
272
+ });
273
+ try {
274
+ ctx.options.onError?.(ctx.withData(err));
275
+ }
276
+ catch (err) {
277
+ ctx.log.error('DurableInterpreter.onErrorError: failed to call onError handler', { error: err instanceof Error ? err.toString() : err });
278
+ ctx.options.onError?.(ctx.withData({
279
+ message: 'Internal server error',
280
+ error: err instanceof Error ? err.toString() : err,
281
+ }));
282
+ }
283
+ return EMPTY;
284
+ }))))
285
+ .subscribe({
286
+ next: async (ctx) => {
287
+ const durationMs = Date.now() - ctx.startTime.getTime();
288
+ ctx.log.info('DurableInterpreter.executionCompleted', {
289
+ durationMs,
290
+ data: ctx.data,
291
+ });
292
+ try {
293
+ ctx.options.onSuccess?.(ctx);
294
+ }
295
+ catch (err) {
296
+ ctx.log.error('DurableInterpreter.onSuccessError: failed to call onSuccess handler', { error: err instanceof Error ? err.toString() : err });
297
+ ctx.options.onSuccess?.(ctx.withData({
298
+ message: 'Internal server error',
299
+ error: err instanceof Error ? err.toString() : err,
300
+ }));
301
+ }
302
+ if (ctx.workflowId) {
303
+ this.log.info('Async workflow completed', {
304
+ workflowId: ctx.workflowId,
305
+ });
306
+ const output = ctx.data ? btoa(JSON.stringify(ctx.data)) : undefined;
307
+ await ctx.queue?.complete({
308
+ id: ctx.workflowId,
309
+ output,
310
+ status: 'completed',
311
+ });
312
+ }
313
+ this.contextProvider.destroy(ctx);
314
+ },
315
+ error: (err) => {
316
+ this.log.error('DurableInterpreter.error', {
317
+ error: err instanceof Error ? err.toString() : err,
318
+ });
319
+ Deno.removeSignalListener('SIGINT', registration.sigintListener);
320
+ },
321
+ complete: () => {
322
+ this.log.info('DurableInterpreter.workflowCompleted');
323
+ Deno.removeSignalListener('SIGINT', registration.sigintListener);
324
+ },
325
+ });
326
+ registration.subscription.add(() => {
327
+ registration.subscription = undefined;
328
+ });
329
+ }
330
+ try {
331
+ this.cronProvider.updateCrons(this.cronRegistry);
332
+ }
333
+ catch (err) {
334
+ this.log.error('DurableInterpreter.updateCronsError', {
335
+ error: err instanceof Error ? err.toString() : err,
336
+ });
337
+ throw new Error('Unable to register scheduler tasks with central cron provider');
338
+ }
339
+ this.webhookServer = webhookApp.listen(port, () => {
340
+ this.log.info(`Express server listening on port ${port}`);
341
+ });
342
+ this.cronServer = cronApp.listen(cronPort, () => {
343
+ this.log.info(`Cron server listening on port ${cronPort}`);
344
+ });
345
+ this.shutdownServer = () => {
346
+ if (this.isShuttingDown) {
347
+ return;
348
+ }
349
+ this.isShuttingDown = true;
350
+ this.log.info('Shutting down server');
351
+ // Close the server
352
+ if (this.webhookServer) {
353
+ this.webhookServer.close();
354
+ }
355
+ if (this.cronServer) {
356
+ this.cronServer.close();
357
+ }
358
+ // Remove all signal listeners
359
+ for (const registration of this.registeredWorkflows) {
360
+ Deno.removeSignalListener('SIGINT', registration.sigintListener);
361
+ // Unsubscribe from all observables
362
+ if (registration.subscription) {
363
+ registration.subscription.unsubscribe();
364
+ }
365
+ // Abort all controllers
366
+ registration.localAbortController.abort();
367
+ }
368
+ // Remove the server shutdown listener
369
+ if (this.shutdownServer) {
370
+ Deno.removeSignalListener('SIGINT', this.shutdownServer);
371
+ }
372
+ };
373
+ Deno.addSignalListener('SIGINT', this.shutdownServer);
374
+ return new Promise((resolve) => {
375
+ let serversClosed = 0;
376
+ const totalServers = [this.webhookServer, this.cronServer].filter(Boolean).length;
377
+ const checkResolve = () => {
378
+ serversClosed++;
379
+ if (serversClosed === totalServers) {
380
+ this.log.info('All servers closed');
381
+ resolve();
382
+ }
383
+ };
384
+ if (this.webhookServer) {
385
+ this.webhookServer.on('close', () => {
386
+ this.log.info('Webhook server closed');
387
+ checkResolve();
388
+ });
389
+ }
390
+ if (this.cronServer) {
391
+ this.cronServer.on('close', () => {
392
+ this.log.info('Cron server closed');
393
+ checkResolve();
394
+ });
395
+ }
396
+ if (!this.webhookServer && !this.cronServer) {
397
+ resolve();
398
+ }
399
+ });
400
+ }
401
+ async stop() {
402
+ this.otelSDK?.shutdown();
403
+ if (this.shutdownServer) {
404
+ this.shutdownServer();
405
+ }
406
+ }
407
+ }
408
+ async function waitForReady(log) {
409
+ const readyCheckUrl = Deno.env.get('READY_CHECK_URL');
410
+ if (!readyCheckUrl) {
411
+ return Promise.resolve();
412
+ }
413
+ const maxAttempts = 40; // should be 20 seconds
414
+ const delay = 500;
415
+ log.info('DurableInterpreter.waitForReady: waiting for network to be ready', { readyCheckUrl });
416
+ for (let i = 0; i < maxAttempts; i++) {
417
+ try {
418
+ const response = await fetch(readyCheckUrl);
419
+ if (response.ok) {
420
+ log.info('DurableInterpreter.waitForReady: network is ready');
421
+ return Promise.resolve();
422
+ }
423
+ }
424
+ catch (err) {
425
+ log.error('DurableInterpreter.waitForReadyError', {
426
+ error: err instanceof Error ? err.toString() : err,
427
+ });
428
+ }
429
+ log.info('DurableInterpreter.waitForReady: retrying...', { attempt: i });
430
+ await new Promise((resolve) => setTimeout(resolve, delay));
431
+ }
432
+ throw new Error(`Network is not ready after ${maxAttempts * (delay / 1000)} seconds`);
433
+ }
@@ -0,0 +1,6 @@
1
+ import { Context } from '../../context/Context.js';
2
+ export declare class ExecutionError extends Error {
3
+ ctx: Context<any>;
4
+ constructor(ctx: Context<any>, message: string, opts?: ErrorOptions);
5
+ }
6
+ //# sourceMappingURL=ExecutionError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionError.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/durable/ExecutionError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,qBAAa,cAAe,SAAQ,KAAK;IACrC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;gBAEN,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAMtE"}
@@ -0,0 +1,13 @@
1
+ export class ExecutionError extends Error {
2
+ constructor(ctx, message, opts) {
3
+ super(message, opts);
4
+ Object.defineProperty(this, "ctx", {
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true,
8
+ value: void 0
9
+ });
10
+ this.name = 'ExecutionError';
11
+ this.ctx = ctx;
12
+ }
13
+ }
@@ -0,0 +1,35 @@
1
+ import { Observable, OperatorFunction } from 'rxjs';
2
+ import { Task } from '../../dsl/Task.js';
3
+ import { Logger } from '../../observability/logging/Logger.js';
4
+ import { ContextOperatorFunction, TaskCompiler, TriggerCompiler } from './compilers/types.js';
5
+ import { Trigger } from '../../dsl/Trigger.js';
6
+ import { ContextProvider } from '../../context/ContextProvider.js';
7
+ import { ContextImpl } from '../../context/Context.js';
8
+ import { ConfigReader, ConnectionProvider, RoundTripperFactory } from '../../dsl/http/types.js';
9
+ import { Router } from 'express';
10
+ import { Tracer } from '@opentelemetry/api';
11
+ import { QueueAPI } from './Queue.js';
12
+ export type DurableCompilerContext = {
13
+ compiler: ObservableCompiler;
14
+ log: Logger;
15
+ tracer: Tracer;
16
+ contextProvider: ContextProvider;
17
+ roundTripperFactory: RoundTripperFactory;
18
+ connectionProvider: ConnectionProvider;
19
+ queueProvider: QueueAPI;
20
+ webhookRouter: Router;
21
+ cronRouter: Router;
22
+ configReader: ConfigReader;
23
+ cronRegistry: Map<string, string>;
24
+ };
25
+ export type CompilerFunc<In = any, Out = any, T extends Task<In, Out> = Task<In, Out>> = (ctx: DurableCompilerContext, task: T) => OperatorFunction<In, Out>;
26
+ export declare class ObservableCompiler {
27
+ private taskCompilers;
28
+ private triggerCompilers;
29
+ constructor();
30
+ compileTask<In = any, Out = any, Index = void>(ctx: DurableCompilerContext, task: Task<In, Out>): ContextOperatorFunction<In, Out, Index>;
31
+ compileTrigger<Out = any, T extends Trigger<Out> = Trigger<Out>>(ctx: DurableCompilerContext, trigger: T, signal: AbortSignal): Observable<ContextImpl<Out, void>>;
32
+ registerTask<In, Out, T extends Task<In, Out>>(compiler: TaskCompiler<In, Out, T>): void;
33
+ registerTrigger<Out, T extends Trigger<Out>>(compiler: TriggerCompiler<Out, T>): void;
34
+ }
35
+ //# sourceMappingURL=ObservableCompiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObservableCompiler.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/durable/ObservableCompiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,IAAI,EAAY,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAO/D,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE9F,OAAO,EAAE,OAAO,EAAe,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,MAAM,sBAAsB,GAAG;IACjC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,aAAa,EAAE,QAAQ,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CACrF,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,CAAC,KACN,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAE/B,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,gBAAgB,CAAgD;;IAkBxE,WAAW,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,KAAK,GAAG,IAAI,EACzC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,GACpB,uBAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC;IAe1C,cAAc,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,EAC3D,GAAG,EAAE,sBAAsB,EAC3B,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,WAAW,GACpB,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAgBrC,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAKjF,eAAe,CAAC,GAAG,EAAE,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC;CAIjF"}
@@ -0,0 +1,69 @@
1
+ import { TaskType } from '../../dsl/Task.js';
2
+ import { backgroundCompiler } from './compilers/background.js';
3
+ import { catchCompiler } from './compilers/catch.js';
4
+ import { chainCompiler } from './compilers/chain.js';
5
+ import { fnCompiler } from './compilers/fn.js';
6
+ import { parallelCompiler } from './compilers/parallel.js';
7
+ import { serialCompiler } from './compilers/serial.js';
8
+ import { unpackCompiler } from './compilers/unpack.js';
9
+ import { TriggerType } from '../../dsl/Trigger.js';
10
+ import { scheduleCompiler } from './compilers/schedule.js';
11
+ import { webhookCompiler } from './compilers/webhook.js';
12
+ import { httpCompiler } from './compilers/http.js';
13
+ import { durableWorkflowCompiler } from './compilers/durableworkflow.js';
14
+ export class ObservableCompiler {
15
+ constructor() {
16
+ Object.defineProperty(this, "taskCompilers", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: new Map()
21
+ });
22
+ Object.defineProperty(this, "triggerCompilers", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: new Map()
27
+ });
28
+ // Register all available compilers
29
+ this.registerTask(parallelCompiler);
30
+ this.registerTask(serialCompiler);
31
+ this.registerTask(catchCompiler);
32
+ this.registerTask(chainCompiler);
33
+ this.registerTask(fnCompiler);
34
+ this.registerTask(backgroundCompiler);
35
+ this.registerTask(unpackCompiler);
36
+ this.registerTask(httpCompiler);
37
+ this.registerTrigger(scheduleCompiler);
38
+ this.registerTrigger(webhookCompiler);
39
+ this.registerTrigger(durableWorkflowCompiler);
40
+ }
41
+ compileTask(ctx, task) {
42
+ const compiler = this.taskCompilers.get(task[TaskType]);
43
+ if (!compiler) {
44
+ throw new Error(`No compiler registered for task type: ${task[TaskType]}`);
45
+ }
46
+ if (!(task instanceof compiler.ctor)) {
47
+ throw new Error(`Task type mismatch: expected ${compiler.ctor.name}, got ${task.constructor.name}`);
48
+ }
49
+ return compiler.compile(ctx, task);
50
+ }
51
+ compileTrigger(ctx, trigger, signal) {
52
+ const compiler = this.triggerCompilers.get(trigger[TriggerType]);
53
+ if (!compiler) {
54
+ throw new Error(`No compiler registered for trigger type: ${trigger[TriggerType]}`);
55
+ }
56
+ if (!(trigger instanceof compiler.ctor)) {
57
+ throw new Error(`Trigger type mismatch: expected ${compiler.ctor.name}, got ${trigger.constructor.name}`);
58
+ }
59
+ return compiler.compile(ctx, trigger, signal);
60
+ }
61
+ registerTask(compiler) {
62
+ const task = new compiler.ctor();
63
+ this.taskCompilers.set(task[TaskType], compiler);
64
+ }
65
+ registerTrigger(compiler) {
66
+ const trigger = new compiler.ctor();
67
+ this.triggerCompilers.set(trigger[TriggerType], compiler);
68
+ }
69
+ }
@@ -0,0 +1,60 @@
1
+ import { Logger } from '../../observability/mod.js';
2
+ export type WorkflowMsgMetadata = {
3
+ parentWorkflowId?: string;
4
+ executionId?: string;
5
+ activationId?: string;
6
+ userId?: string;
7
+ };
8
+ export type Workflows = {
9
+ workflows: WorkflowMsg[];
10
+ };
11
+ export type WorkflowMsg = {
12
+ id?: string;
13
+ projectId?: string;
14
+ group: string;
15
+ payload?: string;
16
+ output?: string;
17
+ status?: 'available' | 'locked' | 'completed' | 'failed';
18
+ attempt?: number;
19
+ timeout?: string;
20
+ createdAt?: string;
21
+ metadata?: WorkflowMsgMetadata;
22
+ };
23
+ export type CompleteWorkflowRequest = {
24
+ id: string;
25
+ output?: string;
26
+ status: 'completed' | 'failed';
27
+ };
28
+ export type FetchWorkflowsRequest = {
29
+ ttl?: number;
30
+ limit?: number;
31
+ group: string;
32
+ projectId?: string;
33
+ };
34
+ export type RescheduleWorkflowRequest = {
35
+ id: string;
36
+ after: string;
37
+ };
38
+ export type SubmitWorkflowsRequest = {
39
+ workflows: WorkflowMsg[];
40
+ };
41
+ export interface QueueAPI {
42
+ complete(request: CompleteWorkflowRequest): Promise<void>;
43
+ submit(request: SubmitWorkflowsRequest): Promise<Workflows>;
44
+ fetchWorkflows(request: FetchWorkflowsRequest): Promise<Workflows | undefined>;
45
+ reschedule(request: RescheduleWorkflowRequest): Promise<void>;
46
+ poll(workflowId: string): Promise<WorkflowMsg>;
47
+ }
48
+ export declare class QueueImpl implements QueueAPI {
49
+ private baseUrl;
50
+ private log;
51
+ private projectId;
52
+ constructor(baseUrl: string, projectId: string, log: Logger);
53
+ static fromEnv(log: Logger): QueueImpl;
54
+ complete(request: CompleteWorkflowRequest): Promise<void>;
55
+ submit(request: SubmitWorkflowsRequest): Promise<Workflows>;
56
+ fetchWorkflows(request: FetchWorkflowsRequest): Promise<Workflows | undefined>;
57
+ reschedule(request: RescheduleWorkflowRequest): Promise<void>;
58
+ poll(workflowId: string): Promise<WorkflowMsg>;
59
+ }
60
+ //# sourceMappingURL=Queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../../src/src/interpreter/durable/Queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAIpD,MAAM,MAAM,mBAAmB,GAAG;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACpB,SAAS,EAAE,WAAW,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,SAAS,EAAE,WAAW,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5D,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC/E,UAAU,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAClD;AAED,qBAAa,SAAU,YAAW,QAAQ;IACtC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAM3D,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAchC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBzD,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC;IA0B3D,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IA8B9E,UAAU,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB7D,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAevD"}