@t4h.framework/dev 0.0.0-experimental-20261007204009 → 0.0.0-experimental-20261008135920

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 (127) hide show
  1. package/CHANGELOG.md +64 -3
  2. package/README.md +95 -19
  3. package/dist/AppProcess.d.ts +16 -2
  4. package/dist/AppProcess.js +31 -4
  5. package/dist/AppProcess.js.map +1 -1
  6. package/dist/HeadlessApp.d.ts +65 -0
  7. package/dist/HeadlessApp.js +166 -0
  8. package/dist/HeadlessApp.js.map +1 -0
  9. package/dist/Server.d.ts +5 -0
  10. package/dist/Server.js +15 -0
  11. package/dist/Server.js.map +1 -1
  12. package/dist/constants/server.d.ts +14 -1
  13. package/dist/constants/server.js +14 -1
  14. package/dist/constants/server.js.map +1 -1
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.js +5 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/integrations/orm.js +12 -1
  19. package/dist/integrations/orm.js.map +1 -1
  20. package/dist/models/DevORMStore.d.ts +18 -0
  21. package/dist/models/DevORMStore.js +7 -0
  22. package/dist/models/DevORMStore.js.map +1 -0
  23. package/dist/models/FrameworkConfig.d.ts +20 -0
  24. package/dist/models/FrameworkConfig.js +2 -0
  25. package/dist/models/FrameworkConfig.js.map +1 -1
  26. package/dist/models/LocalWorkflowRunJobExecutor.d.ts +10 -0
  27. package/dist/models/LocalWorkflowRunJobExecutor.js +23 -0
  28. package/dist/models/LocalWorkflowRunJobExecutor.js.map +1 -0
  29. package/dist/models/PostgresDevORMStore.d.ts +23 -0
  30. package/dist/models/PostgresDevORMStore.js +94 -0
  31. package/dist/models/PostgresDevORMStore.js.map +1 -0
  32. package/dist/models/RuntimeControlServer.d.ts +32 -0
  33. package/dist/models/RuntimeControlServer.js +75 -0
  34. package/dist/models/RuntimeControlServer.js.map +1 -0
  35. package/dist/models/RuntimeDebugLog.d.ts +10 -0
  36. package/dist/models/RuntimeDebugLog.js +32 -0
  37. package/dist/models/RuntimeDebugLog.js.map +1 -0
  38. package/dist/models/RuntimeEvent.d.ts +95 -0
  39. package/dist/models/RuntimeEvent.js +2 -0
  40. package/dist/models/RuntimeEvent.js.map +1 -0
  41. package/dist/models/SqliteDevORMStore.d.ts +16 -0
  42. package/dist/models/SqliteDevORMStore.js +69 -0
  43. package/dist/models/SqliteDevORMStore.js.map +1 -0
  44. package/dist/models/WorkflowRunJob.d.ts +95 -0
  45. package/dist/models/WorkflowRunJob.js +2 -0
  46. package/dist/models/WorkflowRunJob.js.map +1 -0
  47. package/dist/models/WorkflowWorkerPool.d.ts +39 -0
  48. package/dist/models/WorkflowWorkerPool.js +154 -0
  49. package/dist/models/WorkflowWorkerPool.js.map +1 -0
  50. package/dist/models/claims/DevCacheClaim.d.ts +2 -1
  51. package/dist/models/claims/DevCacheClaim.js +17 -6
  52. package/dist/models/claims/DevCacheClaim.js.map +1 -1
  53. package/dist/models/claims/DevORMClaim.d.ts +5 -8
  54. package/dist/models/claims/DevORMClaim.js +22 -55
  55. package/dist/models/claims/DevORMClaim.js.map +1 -1
  56. package/dist/models/claims/DevWorkflowClaim.d.ts +1 -1
  57. package/dist/models/claims/DevWorkflowClaim.js +3 -2
  58. package/dist/models/claims/DevWorkflowClaim.js.map +1 -1
  59. package/dist/services/CallbackToken.service.d.ts +4 -1
  60. package/dist/services/CallbackToken.service.js +10 -3
  61. package/dist/services/CallbackToken.service.js.map +1 -1
  62. package/dist/services/Database.service.d.ts +8 -0
  63. package/dist/services/Database.service.js +18 -3
  64. package/dist/services/Database.service.js.map +1 -1
  65. package/dist/services/RuntimeEvents.service.d.ts +16 -0
  66. package/dist/services/RuntimeEvents.service.js +35 -0
  67. package/dist/services/RuntimeEvents.service.js.map +1 -0
  68. package/dist/services/WorkflowRunAsyncActivityFacade.service.d.ts +2 -0
  69. package/dist/services/WorkflowRunAsyncActivityFacade.service.js +6 -0
  70. package/dist/services/WorkflowRunAsyncActivityFacade.service.js.map +1 -1
  71. package/dist/services/WorkflowRunEvents.service.d.ts +9 -0
  72. package/dist/services/WorkflowRunEvents.service.js +13 -2
  73. package/dist/services/WorkflowRunEvents.service.js.map +1 -1
  74. package/dist/services/WorkflowRunFacade.service.d.ts +1 -0
  75. package/dist/services/WorkflowRunFacade.service.js +3 -0
  76. package/dist/services/WorkflowRunFacade.service.js.map +1 -1
  77. package/dist/services/WorkflowRunScheduler.service.d.ts +62 -0
  78. package/dist/services/WorkflowRunScheduler.service.js +278 -0
  79. package/dist/services/WorkflowRunScheduler.service.js.map +1 -0
  80. package/dist/tools/format-runtime-event.d.ts +3 -0
  81. package/dist/tools/format-runtime-event.js +51 -0
  82. package/dist/tools/format-runtime-event.js.map +1 -0
  83. package/dist/tools/run-workflow-run-job.d.ts +3 -0
  84. package/dist/tools/run-workflow-run-job.js +25 -0
  85. package/dist/tools/run-workflow-run-job.js.map +1 -0
  86. package/dist/tools/runtime-control-client.d.ts +15 -0
  87. package/dist/tools/runtime-control-client.js +54 -0
  88. package/dist/tools/runtime-control-client.js.map +1 -0
  89. package/dist/tools/runtime-registry.d.ts +26 -0
  90. package/dist/tools/runtime-registry.js +57 -0
  91. package/dist/tools/runtime-registry.js.map +1 -0
  92. package/dist/tools/start-runtime-monitor.d.ts +12 -0
  93. package/dist/tools/start-runtime-monitor.js +69 -0
  94. package/dist/tools/start-runtime-monitor.js.map +1 -0
  95. package/dist/tools/to-orm-config.d.ts +3 -0
  96. package/dist/tools/to-orm-config.js +13 -0
  97. package/dist/tools/to-orm-config.js.map +1 -0
  98. package/dist/tools/to-runtime-config.d.ts +3 -0
  99. package/dist/tools/to-runtime-config.js +13 -0
  100. package/dist/tools/to-runtime-config.js.map +1 -0
  101. package/dist/transport/AppProcessJsonRpc.js +17 -4
  102. package/dist/transport/AppProcessJsonRpc.js.map +1 -1
  103. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.d.ts +3 -5
  104. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.js +6 -10
  105. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.js.map +1 -1
  106. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.d.ts +3 -9
  107. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.js +7 -39
  108. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.js.map +1 -1
  109. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.d.ts +5 -5
  110. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.js +29 -15
  111. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.js.map +1 -1
  112. package/dist/use-cases/NextTickWorkflowRun.usecase.d.ts +6 -1
  113. package/dist/use-cases/NextTickWorkflowRun.usecase.js +54 -3
  114. package/dist/use-cases/NextTickWorkflowRun.usecase.js.map +1 -1
  115. package/dist/use-cases/ReceiveWorkflowEvent.usecase.d.ts +10 -2
  116. package/dist/use-cases/ReceiveWorkflowEvent.usecase.js +35 -5
  117. package/dist/use-cases/ReceiveWorkflowEvent.usecase.js.map +1 -1
  118. package/dist/use-cases/RejectAbandonedWorkflowRuns.usecase.d.ts +14 -0
  119. package/dist/use-cases/RejectAbandonedWorkflowRuns.usecase.js +55 -0
  120. package/dist/use-cases/RejectAbandonedWorkflowRuns.usecase.js.map +1 -0
  121. package/dist/workers/app-process.d.ts +8 -0
  122. package/dist/workers/app-process.js +114 -14
  123. package/dist/workers/app-process.js.map +1 -1
  124. package/dist/workers/workflow-worker.d.ts +1 -0
  125. package/dist/workers/workflow-worker.js +58 -0
  126. package/dist/workers/workflow-worker.js.map +1 -0
  127. package/package.json +15 -13
package/CHANGELOG.md CHANGED
@@ -1,11 +1,72 @@
1
1
  # @t4h.framework/dev
2
2
 
3
- ## 0.0.0-experimental-20261007204009
3
+ ## 0.0.0-experimental-20261008135920
4
+
5
+ ### Minor Changes
6
+
7
+ - [#208](https://github.com/tech4humans-brasil/framework/pull/208) [`c312bfb`](https://github.com/tech4humans-brasil/framework/commit/c312bfb0f1b1ddbc40d8ac0ede113c5614aa9df8) Thanks [@tony-tsx](https://github.com/tony-tsx)! - `framework workflows` lists, describes and runs the workflows of the app from
8
+ the terminal, without the dev server: `framework workflows <workflow> run
9
+ --input '<json>'` builds the project, runs the workflow, waits for it
10
+ (`--timeout`) and prints the run as JSON — with the activities, logs and child
11
+ runs under `--trace`. It exits with `0` when the run fulfills, `1` when it is
12
+ rejected or the command fails, and `2` on timeout, so scripts and AI agents can
13
+ test workflows headlessly.
14
+
15
+ `@t4h.framework/dev` exports `HeadlessApp`, the API behind it, and the app
16
+ process resolves its bundle root from `file:` URLs.
17
+
18
+ - [#210](https://github.com/tech4humans-brasil/framework/pull/210) [`a93218a`](https://github.com/tech4humans-brasil/framework/commit/a93218ae284d91de7d94a65e8f306ace0db2d733) Thanks [@tony-tsx](https://github.com/tony-tsx)! - The dev ORM claim can store its rows in Postgres instead of `db.sqlite`:
19
+ set `orm: { connectionString: 'postgres://…' }` in `framework.config.ts`.
20
+ Workers write in parallel instead of waiting on the SQLite file lock, each one
21
+ with its own connection pool, and updates lock their row so concurrent updates
22
+ merge. Each entity gets an `(id text, data jsonb)` table, created on first use;
23
+ `where`, `orderBy` and pagination behave as on SQLite. Without the setting
24
+ nothing changes, and the `connectionString` passed to `new ORM()` is still
25
+ ignored in dev.
26
+
27
+ - [#207](https://github.com/tech4humans-brasil/framework/pull/207) [`92db468`](https://github.com/tech4humans-brasil/framework/commit/92db468f819d3c7d01884526598acd5fbef9b4ef) Thanks [@tony-tsx](https://github.com/tony-tsx)! - Workflows run asynchronously on a pool of worker threads. Starting a run,
28
+ delivering a callback, advancing an activity, a timeout and the settlement of a
29
+ parent run only queue work; a scheduler runs it with at most one step per run
30
+ at a time, keeps each run on the worker that started it and serves callbacks
31
+ ahead of background work. `advance` and callbacks still return the status of
32
+ the activity, but no longer wait for the rest of the workflow.
33
+
34
+ The pool defaults to the available CPUs minus one, 4 jobs per worker, and is set
35
+ with `runtime: { workers, concurrency }` in `framework.config.ts` (`workers: 0`
36
+ keeps everything on the app thread). The runtime database moves to a temporary
37
+ SQLite file in WAL mode shared by the workers, and the dev `CacheClaim` is
38
+ stored there so every worker sees the same cache. A worker that dies rejects
39
+ the runs it held and is replaced.
40
+
41
+ - [#210](https://github.com/tech4humans-brasil/framework/pull/210) [`990c074`](https://github.com/tech4humans-brasil/framework/commit/990c074af498cb7610d310e295ad613dce7a9b52) Thanks [@tony-tsx](https://github.com/tony-tsx)! - The dev runtime publishes what it runs: jobs queued, started and finished
42
+ (with the queue counts), runs created and settled, activities started, waiting
43
+ and settled (with the error of a rejected one), timeouts and lost workers.
44
+ - `--debug` on `framework dev` and `framework workflows <workflow> run` prints
45
+ those events on stderr; `--debug-log <file>` appends them to a file as NDJSON.
46
+ - Every app process registers itself and listens on a local socket (named pipe
47
+ on Windows). `framework runtime ls` lists them, `framework runtime status`
48
+ prints the queue, the jobs running and waiting and the runs in progress, and
49
+ `framework runtime watch` follows the events live (`--json` for NDJSON),
50
+ reconnecting across `dev` rebuilds.
51
+
52
+ `@t4h.framework/dev` exports `listRuntimes`, `requestRuntimeStatus`,
53
+ `watchRuntime` and `formatRuntimeEvent`, and takes `debugLog` on `Server` and
54
+ `HeadlessApp.up`.
55
+
56
+ ## 0.22.6
57
+
58
+ ### Patch Changes
59
+
60
+ - [#214](https://github.com/tech4humans-brasil/framework/pull/214) [`fc4db5f`](https://github.com/tech4humans-brasil/framework/commit/fc4db5fa01454a45a3727b76dbacc215aa6b3ab7) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - `WorkflowClaim.startMany` accepts its inputs as an `Iterable` or an
61
+ `AsyncIterable`, not only an array. The runtime reads them once, as a stream,
62
+ so a batch no longer has to fit in memory before its first child starts.
63
+
64
+ ## 0.22.5
4
65
 
5
66
  ### Patch Changes
6
67
 
7
- - Updated dependencies [[`752ecc5`](https://github.com/tech4humans-brasil/framework/commit/752ecc5a5437a1e73492c6b52e41792f0c7ba629)]:
8
- - @t4h.framework/vite-panel-plugin@0.0.0-experimental-20261007204009
68
+ - Updated dependencies [[`8f50cc5`](https://github.com/tech4humans-brasil/framework/commit/8f50cc5c494fd76b08536a08da397d2255d47d31)]:
69
+ - @t4h.framework/vite-panel-plugin@0.4.0
9
70
 
10
71
  ## 0.22.4
11
72
 
package/README.md CHANGED
@@ -7,7 +7,7 @@ Local development runtime for [T4H Framework](https://github.com/tech4humans-bra
7
7
  When you run `framework dev` (via `@t4h.framework/cli`), this package powers the experience behind the scenes:
8
8
 
9
9
  1. **TypeScript watch** — compiles your app on every change.
10
- 2. **App process** — forks a child Node process that loads your compiled `App` and runs the workflow engine on an in-memory SQLite database.
10
+ 2. **App process** — forks a child Node process that loads your compiled `App`, queues every workflow step and runs them on a pool of worker threads sized to the machine (see [Execution](#execution)).
11
11
  3. **HTTP server** — a [Hono](https://hono.dev) app that exposes your workflows (create runs, advance pending activities), enforces the workflow authorization and adds `/_dev` routes for tooling.
12
12
  4. **Vite** — a Vite dev server in middleware mode serves the built-in panel and anything else that is not an API route.
13
13
  5. **Dev claims** — provides local implementations for ORM, HTTP, file system, cache, SMTP, and more.
@@ -23,16 +23,20 @@ flowchart TB
23
23
  HTTP --> Auth
24
24
  end
25
25
 
26
- subgraph child ["Child process (app-process worker)"]
27
- App["User App"]
28
- Engine["Workflow engine + SQLite :memory:"]
29
- Claims["Dev claims"]
30
- App --> Engine
31
- Claims --> App
26
+ subgraph child ["Child process (app-process)"]
27
+ Queue["Scheduler queue + timers"]
28
+ DB[("Runtime SQLite (temp file, WAL)")]
29
+ subgraph workers ["Worker threads"]
30
+ App["User App + dev claims"]
31
+ end
32
+ Queue -->|"jobs"| App
33
+ App -->|"child runs, timeouts, events"| Queue
34
+ Queue --- DB
35
+ App --- DB
32
36
  end
33
37
 
34
- Fork --> App
35
- HTTP <-->|"IPC / JSON-RPC"| Engine
38
+ Fork --> Queue
39
+ HTTP <-->|"IPC / JSON-RPC"| Queue
36
40
  ```
37
41
 
38
42
  ## Installation
@@ -162,14 +166,64 @@ Every `/projects` route requires an authorization: the workflow `authorization`
162
166
 
163
167
  Everything else is handed to Vite, which serves the panel that ships with this package: open the base URL to browse the workflows and start runs from their schema, follow runs live with the execution trace of each one (activities as a waterfall, child runs nested, input, output, duration, logs, the activity that failed) and advance waiting activities. Plugins from the project's `vite.config.*` (or `vite.plugins`) are served by the same Vite.
164
168
 
169
+ ## Execution
170
+
171
+ Starting a run, delivering a callback or advancing an activity only queues work; the app process answers right away and a scheduler hands each step (a _job_) to a pool of `worker_threads`. Every worker loads its own copy of your `App`, so a CPU-heavy activity blocks only its worker — the HTTP API, the panel and the other runs keep going. No message broker is involved: the queue lives in the app process, like the rest of the dev state.
172
+
173
+ - **Capacity** — `workers` threads (default: available CPUs − 1) each run up to `concurrency` jobs at once (default: 4). Extra work waits in the queue.
174
+ - **Order** — a run never has two jobs in flight, and all jobs of a run go to the worker that started it. Callbacks and advances jump ahead of background work.
175
+ - **Responses** — `advance` and callbacks still run the activity's `advance` and return its status; the steps after it run in the background (follow them through `run:updated`).
176
+ - **Failures** — if a worker dies, its in-flight jobs fail, the runs it held are rejected (`The workflow worker running this run stopped`) and a new worker takes its place.
177
+
178
+ Tune it in `framework.config.ts`:
179
+
180
+ ```typescript
181
+ import { defineConfig } from '@t4h.framework/dev/config'
182
+
183
+ export default defineConfig({
184
+ runtime: {
185
+ workers: 2, // 0 runs workflows on the app process thread
186
+ concurrency: 4,
187
+ },
188
+ })
189
+ ```
190
+
191
+ ### Debugging and monitoring
192
+
193
+ The runtime publishes an event for every job it queues, starts and finishes (with the queue counts at that moment), every run created and settled, every activity started, waiting and settled, every timeout and every worker lost.
194
+
195
+ - **Debug log** — `framework dev --debug` / `framework workflows <workflow> run --debug` print them on stderr; `--debug-log <file>` appends them to a file as NDJSON. Programmatically: `debugLog: '-'` or a path on `Server` and `HeadlessApp.up`.
196
+ - **Another process** — each app process registers in `<tmpdir>/t4h-framework/runtimes` and listens on a local socket (named pipe on Windows). `framework runtime ls | status | watch` reads it; from code, `listRuntimes()`, `requestRuntimeStatus(runtime)` and `watchRuntime(runtime, { onEvent })`.
197
+
165
198
  ## State
166
199
 
167
- Workflow runs, activities, pending async activities and logs live in an in-memory SQLite database (`node:sqlite`) inside the app process. Every successful build forks a fresh process, so **a rebuild resets all runs, timers and pending activities**; the `manifest` SSE event tells a UI to reload. There is no durability, queue or resume in the dev server by design.
200
+ Workflow runs, activities, pending async activities, logs and the cache live in a SQLite database (`node:sqlite`) in a temporary file the app process creates and removes on exit; the workers open the same file (WAL mode). With `workers: 0` it stays in memory. Every successful build forks a fresh process, so **a rebuild resets all runs, timers and pending activities**; the `manifest` SSE event tells a UI to reload. The queue is not durable either: nothing resumes across rebuilds, by design.
168
201
 
169
- Sync activities run inline, `sleep` and other timers use `setTimeout`, and child workflows started with `startWorkflow` / `startWorkflowMany` run in parallel.
202
+ Sync activities run inside the job of their run, `sleep` and other timeouts are timers in the app process that queue the run when they fire, and child workflows started with `startWorkflow` / `startWorkflowMany` run in parallel across the workers.
170
203
 
171
204
  The ORM claim is the exception: its rows live in `db.sqlite` next to your `package.json` and survive rebuilds and restarts (add it to `.gitignore`). Delete the file to start over. The previous `db.json` is no longer read.
172
205
 
206
+ ### ORM on Postgres
207
+
208
+ SQLite takes one write at a time, so with many workers writing through the ORM they wait on each other. Point the ORM claim at a Postgres database instead with `orm.connectionString` in `framework.config.ts`:
209
+
210
+ ```typescript
211
+ import { defineConfig } from '@t4h.framework/dev/config'
212
+
213
+ export default defineConfig({
214
+ orm: { connectionString: process.env.DEV_DATABASE_URL },
215
+ })
216
+ ```
217
+
218
+ Each entity gets a table `(id text primary key, data jsonb)` in the connection's current schema, created on first use; `where`, `orderBy` and pagination keep the same semantics as on SQLite. Every worker opens its own pool (as many connections as its `concurrency`), and an update locks its row, so concurrent updates from different workers merge instead of overwriting each other. Rows survive rebuilds and restarts; drop the tables (or the schema) to start over.
219
+
220
+ It is opt-in on purpose: the `connectionString` you pass to `new ORM()` is not used, so a `DATABASE_URL` aimed at a shared database never receives dev writes. Use a database (or a schema, with `?options=-c%20search_path%3Dmy_schema`) of its own: a table with the entity's name and another layout is refused. Leaving the value unset (e.g. `DEV_DATABASE_URL` not exported) keeps `db.sqlite`.
221
+
222
+ ```bash
223
+ docker run -d --name framework-dev-db -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:17
224
+ export DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
225
+ ```
226
+
173
227
  ## Programmatic usage
174
228
 
175
229
  ```typescript
@@ -209,18 +263,40 @@ await server.down()
209
263
 
210
264
  `vite: false` disables Vite; `vite.root` / `vite.configFile` point at another Vite project. The server logs the listening URL, build output and the routes of every workflow through `logger` (default `console`, `false` to silence). A manifest with a workflow that has no authorization (and no app default) emits `error` with a `WorkflowAuthorizationMissingError`; `framework dev` exits with code 1 in that case.
211
265
 
266
+ ### Headless runs
267
+
268
+ `HeadlessApp` builds the project once and loads it without the HTTP server or Vite — what `framework workflows` uses to run a workflow from the terminal:
269
+
270
+ ```typescript
271
+ import { HeadlessApp } from '@t4h.framework/dev'
272
+
273
+ const app = await HeadlessApp.up({ entrypoint: './package.json', env: {} })
274
+
275
+ try {
276
+ const { run, timedOut, waiting, trace } = await app.run(
277
+ 'create-invoice',
278
+ { customerId: 'c-1', amount: 100 },
279
+ { timeoutInMs: 60_000, trace: true },
280
+ )
281
+ } finally {
282
+ await app.down()
283
+ }
284
+ ```
285
+
286
+ `run()` resolves once the run settles or the timeout elapses (`timedOut: true`, with the async activities still waiting in `waiting`); `trace` adds the activities, logs and child runs. Unknown workflows, invalid input and build failures throw a `HeadlessAppError` with `status` and `details`. The app's stdout goes to stderr.
287
+
212
288
  ## Dev claims
213
289
 
214
290
  In production, claims are fulfilled by the runtime (database connections, real HTTP clients, etc.). During local development, `@t4h.framework/dev` registers in-memory substitutes:
215
291
 
216
- | Claim | Dev implementation |
217
- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
218
- | `ORMClaim` | SQLite file `db.sqlite` in the project directory; `where` keeps the Mongo-like semantics (`$like`, `$ilike`, `$or`, ...) |
219
- | `HttpClientRequestClaim` | Real HTTP via `undici` |
220
- | `FileSystemClaim` | Local file system with dev binary codec |
221
- | `SmtpSendEmailClaim` | Captures emails in memory (no delivery) |
222
- | `CacheClaim` | In-memory cache |
223
- | `WorkflowClaim` | Runs workflows through the local workflow engine |
292
+ | Claim | Dev implementation |
293
+ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
294
+ | `ORMClaim` | SQLite file `db.sqlite` in the project directory, or Postgres with `orm.connectionString`; `where` keeps the Mongo-like semantics (`$like`, `$ilike`, `$or`, ...) |
295
+ | `HttpClientRequestClaim` | Real HTTP via `undici` |
296
+ | `FileSystemClaim` | Local file system with dev binary codec |
297
+ | `SmtpSendEmailClaim` | Captures emails in memory (no delivery) |
298
+ | `CacheClaim` | Runtime SQLite table shared by every worker (reset on rebuild) |
299
+ | `WorkflowClaim` | Runs workflows through the local workflow engine |
224
300
 
225
301
  Import the full claim registry:
226
302
 
@@ -1,6 +1,8 @@
1
1
  import { fork } from 'node:child_process';
2
2
  import { EventEmitter } from 'node:events';
3
3
  import type { App } from '@t4h.framework/core';
4
+ import type { FrameworkORMConfig, FrameworkRuntimeConfig } from './models/FrameworkConfig.js';
5
+ import type { RuntimeKind } from './tools/runtime-registry.js';
4
6
  export type AppManifest = ReturnType<App['toManifest']>;
5
7
  export type AppProcessState = 'idle' | 'starting' | 'ready' | 'exited';
6
8
  export declare class AppProcessNotReadyError extends Error {
@@ -11,26 +13,38 @@ export interface AppProcessOptions {
11
13
  readyTimeoutInMs?: number;
12
14
  killTimeoutInMs?: number;
13
15
  fork?: typeof fork;
16
+ /** Where the app writes its stdout; `stderr` keeps the parent stdout clean. */
17
+ stdout?: 'inherit' | 'stderr';
14
18
  }
15
19
  export interface AppProcessUpOptions {
16
20
  /** Public origin of the HTTP server in front of this process; webhooks build callback URLs on it. */
17
21
  serverUrl?: string;
22
+ /** How the app runs workflows; see `FrameworkConfig.runtime`. */
23
+ runtime?: FrameworkRuntimeConfig;
24
+ /** Where the ORM claim stores its rows; see `FrameworkConfig.orm`. */
25
+ orm?: FrameworkORMConfig;
26
+ /** Advertised to `framework runtime` so it can tell runtimes apart. */
27
+ kind?: RuntimeKind;
28
+ projectDir?: string;
29
+ /** Logs every runtime event: `-` to stderr, or a file path (NDJSON). */
30
+ debugLog?: string;
18
31
  }
19
32
  export declare class AppProcess extends EventEmitter {
20
33
  private readonly workerPath;
21
34
  private readonly readyTimeoutInMs;
22
35
  private readonly killTimeoutInMs;
23
36
  private readonly forkProcess;
37
+ private readonly stdout;
24
38
  private readonly server;
25
39
  private child;
26
40
  private client;
27
41
  private ready;
28
42
  private currentManifest;
29
43
  private currentState;
30
- constructor({ workerPath, readyTimeoutInMs, killTimeoutInMs, fork: forkProcess, }?: AppProcessOptions);
44
+ constructor({ workerPath, readyTimeoutInMs, killTimeoutInMs, fork: forkProcess, stdout, }?: AppProcessOptions);
31
45
  get manifest(): AppManifest | null;
32
46
  get state(): AppProcessState;
33
- up(entrypoint: string, env: Record<string, string>, { serverUrl }?: AppProcessUpOptions): Promise<AppManifest>;
47
+ up(entrypoint: string, env: Record<string, string>, { serverUrl, runtime, orm, kind, projectDir, debugLog, }?: AppProcessUpOptions): Promise<AppManifest>;
34
48
  down(): Promise<void>;
35
49
  private kill;
36
50
  whenReady(): Promise<AppManifest>;
@@ -3,29 +3,39 @@ import { EventEmitter } from 'node:events';
3
3
  import path from 'node:path';
4
4
  import { styleText } from 'node:util';
5
5
  import Type from 'typebox';
6
- import { APP_KILL_TIMEOUT_IN_MS, APP_READY_TIMEOUT_IN_MS, SERVER_URL_ARG, WORKFLOW_RUN_EVENTS, } from './constants/server.js';
6
+ import { APP_KILL_TIMEOUT_IN_MS, APP_READY_TIMEOUT_IN_MS, DEBUG_LOG_ARG, ORM_CONNECTION_STRING_ENV, PROJECT_DIR_ARG, RUNTIME_CONCURRENCY_ARG, RUNTIME_KIND_ARG, RUNTIME_WORKERS_ARG, SERVER_URL_ARG, WORKFLOW_RUN_EVENTS, } from './constants/server.js';
7
7
  import { JSONRPCClient } from './models/JSONRPCClient.js';
8
8
  import { JSONRPCServer, JSONRPCServerMethod } from './models/JSONRPCServer.js';
9
9
  export class AppProcessNotReadyError extends Error {
10
10
  name = 'AppProcessNotReadyError';
11
11
  }
12
+ /** Only `orm.connectionString` turns Postgres on, never an inherited variable. */
13
+ function appProcessEnv(orm) {
14
+ const env = { ...process.env };
15
+ delete env[ORM_CONNECTION_STRING_ENV];
16
+ if (orm?.connectionString)
17
+ env[ORM_CONNECTION_STRING_ENV] = orm.connectionString;
18
+ return env;
19
+ }
12
20
  export class AppProcess extends EventEmitter {
13
21
  workerPath;
14
22
  readyTimeoutInMs;
15
23
  killTimeoutInMs;
16
24
  forkProcess;
25
+ stdout;
17
26
  server;
18
27
  child = null;
19
28
  client = null;
20
29
  ready = null;
21
30
  currentManifest = null;
22
31
  currentState = 'idle';
23
- constructor({ workerPath = path.join(import.meta.dirname, 'workers', 'app-process.js'), readyTimeoutInMs = APP_READY_TIMEOUT_IN_MS, killTimeoutInMs = APP_KILL_TIMEOUT_IN_MS, fork: forkProcess = fork, } = {}) {
32
+ constructor({ workerPath = path.join(import.meta.dirname, 'workers', 'app-process.js'), readyTimeoutInMs = APP_READY_TIMEOUT_IN_MS, killTimeoutInMs = APP_KILL_TIMEOUT_IN_MS, fork: forkProcess = fork, stdout = 'inherit', } = {}) {
24
33
  super();
25
34
  this.workerPath = workerPath;
26
35
  this.readyTimeoutInMs = readyTimeoutInMs;
27
36
  this.killTimeoutInMs = killTimeoutInMs;
28
37
  this.forkProcess = forkProcess;
38
+ this.stdout = stdout;
29
39
  this.server = new JSONRPCServer([
30
40
  new JSONRPCServerMethod('manifest', { schema: [Type.Any()] }, (manifest) => this.onManifest(manifest)),
31
41
  ...WORKFLOW_RUN_EVENTS.map(event => new JSONRPCServerMethod(event, { schema: [Type.Any()] }, (payload) => void this.emit(event, payload))),
@@ -39,7 +49,7 @@ export class AppProcess extends EventEmitter {
39
49
  get state() {
40
50
  return this.currentState;
41
51
  }
42
- async up(entrypoint, env, { serverUrl } = {}) {
52
+ async up(entrypoint, env, { serverUrl, runtime, orm, kind, projectDir, debugLog, } = {}) {
43
53
  const previous = this.child;
44
54
  this.child = null;
45
55
  this.client?.rejectPending(new AppProcessNotReadyError('App process is restarting'));
@@ -51,8 +61,25 @@ export class AppProcess extends EventEmitter {
51
61
  const child = this.forkProcess(this.workerPath, [
52
62
  entrypoint,
53
63
  ...(serverUrl ? [`${SERVER_URL_ARG}${serverUrl}`] : []),
64
+ ...(runtime?.workers !== undefined
65
+ ? [`${RUNTIME_WORKERS_ARG}${runtime.workers}`]
66
+ : []),
67
+ ...(runtime?.concurrency !== undefined
68
+ ? [`${RUNTIME_CONCURRENCY_ARG}${runtime.concurrency}`]
69
+ : []),
70
+ ...(kind ? [`${RUNTIME_KIND_ARG}${kind}`] : []),
71
+ ...(projectDir ? [`${PROJECT_DIR_ARG}${projectDir}`] : []),
72
+ ...(debugLog ? [`${DEBUG_LOG_ARG}${debugLog}`] : []),
54
73
  ...Object.entries(env).map(([name, value]) => `${name}=${value}`),
55
- ], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'] });
74
+ ], {
75
+ env: appProcessEnv(orm),
76
+ stdio: [
77
+ 'ignore',
78
+ this.stdout === 'stderr' ? process.stderr : 'inherit',
79
+ 'inherit',
80
+ 'ipc',
81
+ ],
82
+ });
56
83
  const client = new JSONRPCClient(message => {
57
84
  child.send(message);
58
85
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AppProcess.js","sourceRoot":"","sources":["../src/AppProcess.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppProcess.js","sourceRoot":"","sources":["../src/AppProcess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { AppProcess, type AppManifest } from './AppProcess.js';
2
+ export declare const DEFAULT_HEADLESS_RUN_TIMEOUT_IN_MS = 60000;
3
+ export type HeadlessAppProcess = Pick<AppProcess, 'call' | 'down'> & Pick<NodeJS.EventEmitter, 'on' | 'off'>;
4
+ export interface HeadlessAppUpOptions {
5
+ /** Path to the project's `package.json` (or its directory). */
6
+ entrypoint: string;
7
+ env?: Record<string, string>;
8
+ /** Logs every runtime event: `-` to stderr, or a file path (NDJSON). */
9
+ debugLog?: string;
10
+ }
11
+ export interface HeadlessRunOptions {
12
+ /** Gives up waiting after this long; the run keeps its `running` status. */
13
+ timeoutInMs?: number;
14
+ /** Adds the activities, logs and child runs of the run to the result. */
15
+ trace?: boolean;
16
+ }
17
+ export interface HeadlessRunSummary {
18
+ id: string;
19
+ workflow: string;
20
+ status: 'running' | 'fulfilled' | 'rejected';
21
+ [key: string]: unknown;
22
+ }
23
+ export interface HeadlessRunTrace {
24
+ activities: unknown[];
25
+ logs: unknown[];
26
+ children: unknown[];
27
+ }
28
+ export interface HeadlessRunResult {
29
+ run: HeadlessRunSummary & {
30
+ input: unknown;
31
+ output: unknown;
32
+ };
33
+ /** True when the run was still running when `timeoutInMs` elapsed. */
34
+ timedOut: boolean;
35
+ /** Async activities still waiting for a callback, advance or timeout. */
36
+ waiting: unknown[];
37
+ trace?: HeadlessRunTrace;
38
+ }
39
+ export declare class HeadlessAppError extends Error {
40
+ readonly status: number | undefined;
41
+ readonly details: unknown;
42
+ readonly name = "HeadlessAppError";
43
+ constructor(message: string, status: number | undefined, details: unknown);
44
+ }
45
+ /**
46
+ * Builds the project once and loads it in an app process without the HTTP
47
+ * server or the panel, to start workflows from code or a terminal.
48
+ */
49
+ export declare class HeadlessApp {
50
+ private readonly appProcess;
51
+ readonly manifest: AppManifest;
52
+ private readonly outDir;
53
+ constructor(appProcess: HeadlessAppProcess, manifest: AppManifest, outDir?: string | null);
54
+ static up({ entrypoint, env, debugLog, }: HeadlessAppUpOptions): Promise<HeadlessApp>;
55
+ get workflows(): AppManifest['workflows'];
56
+ /** Starts a run and waits until it settles or `timeoutInMs` elapses. */
57
+ run(workflowId: string, input: unknown, { timeoutInMs, trace, }?: HeadlessRunOptions): Promise<HeadlessRunResult>;
58
+ down(): Promise<void>;
59
+ private waitUntilSettled;
60
+ private trace;
61
+ /** Activities in the order they ran. */
62
+ private findActivities;
63
+ private findAll;
64
+ private call;
65
+ }
@@ -0,0 +1,166 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { stripVTControlCharacters } from 'node:util';
5
+ import { AppProcess } from './AppProcess.js';
6
+ import { JSONRPCError } from './models/JSONRPCError.js';
7
+ import { loadFrameworkConfig } from './tools/load-framework-config.js';
8
+ import { mkdirOutDirProjectFromTsConfigPathAndJsonPackagePath } from './tools/mkdir-out-dir-project-from-ts-config-path-and-json-package-path.js';
9
+ import { resolvePackageJsonPath } from './tools/resolve-package-json-path.js';
10
+ import { resolveTsconfigFromPackageJsonPath } from './tools/resolve-tsconfig-path-from-package-json-path.js';
11
+ import { toORMConfig } from './tools/to-orm-config.js';
12
+ import { toRuntimeConfig } from './tools/to-runtime-config.js';
13
+ import { tsBuild } from './tools/ts-build.js';
14
+ const PAGE_LIMIT = 100;
15
+ export const DEFAULT_HEADLESS_RUN_TIMEOUT_IN_MS = 60_000;
16
+ export class HeadlessAppError extends Error {
17
+ status;
18
+ details;
19
+ name = 'HeadlessAppError';
20
+ constructor(message, status, details) {
21
+ super(message);
22
+ this.status = status;
23
+ this.details = details;
24
+ }
25
+ }
26
+ /**
27
+ * Builds the project once and loads it in an app process without the HTTP
28
+ * server or the panel, to start workflows from code or a terminal.
29
+ */
30
+ export class HeadlessApp {
31
+ appProcess;
32
+ manifest;
33
+ outDir;
34
+ constructor(appProcess, manifest, outDir = null) {
35
+ this.appProcess = appProcess;
36
+ this.manifest = manifest;
37
+ this.outDir = outDir;
38
+ }
39
+ static async up({ entrypoint, env = {}, debugLog, }) {
40
+ const packageJsonPath = await resolvePackageJsonPath(entrypoint);
41
+ const tsConfigPath = await resolveTsconfigFromPackageJsonPath(packageJsonPath);
42
+ const projectDir = path.dirname(packageJsonPath);
43
+ const config = await loadFrameworkConfig(projectDir);
44
+ const runtime = toRuntimeConfig(config.runtime);
45
+ const orm = toORMConfig(config.orm);
46
+ const { outDir } = await mkdirOutDirProjectFromTsConfigPathAndJsonPackagePath(tsConfigPath, packageJsonPath);
47
+ const removeOutDir = () => fs.promises.rm(outDir, { recursive: true, force: true });
48
+ try {
49
+ const build = tsBuild(tsConfigPath, {
50
+ outDir: path.join(outDir, 'dist'),
51
+ sourceMap: true,
52
+ declaration: false,
53
+ declarationMap: false,
54
+ });
55
+ if (!build.ok)
56
+ throw new HeadlessAppError('Build failed', undefined, {
57
+ diagnostics: build.diagnostics.map(stripVTControlCharacters),
58
+ });
59
+ const { default: packageJson } = await import(packageJsonPath, {
60
+ with: { type: 'json' },
61
+ });
62
+ if (typeof packageJson.main !== 'string')
63
+ throw new Error('Main is not a string');
64
+ const appProcess = new AppProcess({ stdout: 'stderr' });
65
+ const manifest = await appProcess
66
+ .up(pathToFileURL(path.join(outDir, 'dist', packageJson.main)).href, env, { runtime, orm, kind: 'headless', projectDir, debugLog })
67
+ .catch(async (error) => {
68
+ await appProcess.down();
69
+ throw error;
70
+ });
71
+ return new HeadlessApp(appProcess, manifest, outDir);
72
+ }
73
+ catch (error) {
74
+ await removeOutDir();
75
+ throw error;
76
+ }
77
+ }
78
+ get workflows() {
79
+ return this.manifest.workflows;
80
+ }
81
+ /** Starts a run and waits until it settles or `timeoutInMs` elapses. */
82
+ async run(workflowId, input, { timeoutInMs = DEFAULT_HEADLESS_RUN_TIMEOUT_IN_MS, trace = false, } = {}) {
83
+ const settled = new Set();
84
+ const waiters = new Map();
85
+ const onUpdated = (payload) => {
86
+ if (payload.status === 'running')
87
+ return;
88
+ settled.add(payload.id);
89
+ waiters.get(payload.id)?.();
90
+ };
91
+ this.appProcess.on('run:updated', onUpdated);
92
+ try {
93
+ const { id } = await this.call('workflow.run', workflowId, input);
94
+ const timedOut = !(await this.waitUntilSettled(id, settled, waiters, timeoutInMs));
95
+ const run = await this.call('workflow.runs.findById', id);
96
+ const activities = await this.findActivities(id);
97
+ return {
98
+ run,
99
+ timedOut,
100
+ waiting: activities.filter(isWaiting),
101
+ ...(trace ? { trace: await this.trace(id, activities) } : {}),
102
+ };
103
+ }
104
+ finally {
105
+ this.appProcess.off('run:updated', onUpdated);
106
+ }
107
+ }
108
+ async down() {
109
+ await this.appProcess.down();
110
+ if (this.outDir)
111
+ await fs.promises.rm(this.outDir, { recursive: true, force: true });
112
+ }
113
+ async waitUntilSettled(id, settled, waiters, timeoutInMs) {
114
+ const done = Promise.withResolvers();
115
+ waiters.set(id, () => done.resolve(true));
116
+ const timer = setTimeout(() => done.resolve(false), timeoutInMs);
117
+ try {
118
+ // The run may have settled before `workflow.run` answered.
119
+ if (settled.has(id))
120
+ return true;
121
+ const current = await this.call('workflow.runs.findById', id);
122
+ if (current.status !== 'running')
123
+ return true;
124
+ return await done.promise;
125
+ }
126
+ finally {
127
+ clearTimeout(timer);
128
+ waiters.delete(id);
129
+ }
130
+ }
131
+ async trace(runId, activities) {
132
+ const detailed = await Promise.all(activities.map(activity => this.call('workflow.runs.activities.findById', runId, activity.id)));
133
+ const logs = await this.findAll('workflow.runs.logs.find', 'logs', runId);
134
+ const children = await this.findAll('workflow.runs.find', 'runs', undefined, { parentRun: runId });
135
+ return { activities: detailed, logs: logs.reverse(), children };
136
+ }
137
+ /** Activities in the order they ran. */
138
+ async findActivities(runId) {
139
+ const activities = await this.findAll('workflow.runs.activities.find', 'activities', runId);
140
+ return activities.reverse();
141
+ }
142
+ async findAll(method, key, runId, query = {}) {
143
+ const items = [];
144
+ for (let offset = 0;; offset += PAGE_LIMIT) {
145
+ const page = { ...query, limit: PAGE_LIMIT, offset };
146
+ const result = await this.call(method, ...(runId === undefined ? [page] : [runId, page]));
147
+ items.push(...result[key]);
148
+ if (offset + PAGE_LIMIT >= result.count)
149
+ return items;
150
+ }
151
+ }
152
+ async call(method, ...params) {
153
+ try {
154
+ return await this.appProcess.call(method, ...params);
155
+ }
156
+ catch (error) {
157
+ if (!(error instanceof JSONRPCError))
158
+ throw error;
159
+ throw new HeadlessAppError(error.message, error.data?.status, error.data?.details);
160
+ }
161
+ }
162
+ }
163
+ function isWaiting(activity) {
164
+ return activity.kind === 'async' && activity.pendingStatus === 'pending';
165
+ }
166
+ //# sourceMappingURL=HeadlessApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeadlessApp.js","sourceRoot":"","sources":["../src/HeadlessApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAA;AAEpD,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,oDAAoD,EAAE,MAAM,4EAA4E,CAAA;AACjJ,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,EAAE,kCAAkC,EAAE,MAAM,yDAAyD,CAAA;AAC5G,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,UAAU,GAAG,GAAG,CAAA;AAEtB,MAAM,CAAC,MAAM,kCAAkC,GAAG,MAAM,CAAA;AA0CxD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAKvB;IACA;IALO,IAAI,GAAG,kBAAkB,CAAA;IAElD,YACE,OAAe,EACC,MAA0B,EAC1B,OAAgB;QAEhC,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,WAAM,GAAN,MAAM,CAAoB;QAC1B,YAAO,GAAP,OAAO,CAAS;IAGlC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAEH;IACD;IACC;IAHnB,YACmB,UAA8B,EAC/B,QAAqB,EACpB,SAAwB,IAAI;QAF5B,eAAU,GAAV,UAAU,CAAoB;QAC/B,aAAQ,GAAR,QAAQ,CAAa;QACpB,WAAM,GAAN,MAAM,CAAsB;IAC5C,CAAC;IAEG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACrB,UAAU,EACV,GAAG,GAAG,EAAE,EACR,QAAQ,GACa;QACrB,MAAM,eAAe,GAAG,MAAM,sBAAsB,CAAC,UAAU,CAAC,CAAA;QAChE,MAAM,YAAY,GAChB,MAAM,kCAAkC,CAAC,eAAe,CAAC,CAAA;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QAEhD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAA;QAEpD,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC/C,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAEnC,MAAM,EAAE,MAAM,EAAE,GACd,MAAM,oDAAoD,CACxD,YAAY,EACZ,eAAe,CAChB,CAAA;QAEH,MAAM,YAAY,GAAG,GAAG,EAAE,CACxB,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAE1D,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE;gBAClC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;gBACjC,SAAS,EAAE,IAAI;gBACf,WAAW,EAAE,KAAK;gBAClB,cAAc,EAAE,KAAK;aACtB,CAAC,CAAA;YAEF,IAAI,CAAC,KAAK,CAAC,EAAE;gBACX,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE,SAAS,EAAE;oBACpD,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,wBAAwB,CAAC;iBAC7D,CAAC,CAAA;YAEJ,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE;gBAC7D,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACvB,CAAC,CAAA;YAEF,IAAI,OAAO,WAAW,CAAC,IAAI,KAAK,QAAQ;gBACtC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;YAEzC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;YAEvD,MAAM,QAAQ,GAAG,MAAM,UAAU;iBAC9B,EAAE,CACD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAC/D,GAAG,EACH,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,CACzD;iBACA,KAAK,CAAC,KAAK,EAAC,KAAK,EAAC,EAAE;gBACnB,MAAM,UAAU,CAAC,IAAI,EAAE,CAAA;gBAEvB,MAAM,KAAK,CAAA;YACb,CAAC,CAAC,CAAA;YAEJ,OAAO,IAAI,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,EAAE,CAAA;YAEpB,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAA;IAChC,CAAC;IAED,wEAAwE;IACjE,KAAK,CAAC,GAAG,CACd,UAAkB,EAClB,KAAc,EACd,EACE,WAAW,GAAG,kCAAkC,EAChD,KAAK,GAAG,KAAK,MACS,EAAE;QAE1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;QACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAA;QAE7C,MAAM,SAAS,GAAG,CAAC,OAA2B,EAAE,EAAE;YAChD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAM;YAExC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YAEvB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,CAAA;QAC7B,CAAC,CAAA;QAED,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;QAE5C,IAAI,CAAC;YACH,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAC5B,cAAc,EACd,UAAU,EACV,KAAK,CACN,CAAA;YAED,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAC5C,EAAE,EACF,OAAO,EACP,OAAO,EACP,WAAW,CACZ,CAAC,CAAA;YAEF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CACzB,wBAAwB,EACxB,EAAE,CACH,CAAA;YAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;YAEhD,OAAO;gBACL,GAAG;gBACH,QAAQ;gBACR,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;gBACrC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9D,CAAA;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;QAC/C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;QAE5B,IAAI,IAAI,CAAC,MAAM;YACb,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACvE,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,EAAU,EACV,OAA4B,EAC5B,OAAgC,EAChC,WAAmB;QAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAW,CAAA;QAE7C,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;QAEzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAA;QAEhE,IAAI,CAAC;YACH,2DAA2D;YAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAA;YAEhC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAC7B,wBAAwB,EACxB,EAAE,CACH,CAAA;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA;YAE7C,OAAO,MAAM,IAAI,CAAC,OAAO,CAAA;QAC3B,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAA;YAEnB,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAK,CACjB,KAAa,EACb,UAAqC;QAErC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CACxB,IAAI,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CACnE,CACF,CAAA;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAC7B,yBAAyB,EACzB,MAAM,EACN,KAAK,CACN,CAAA;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CACjC,oBAAoB,EACpB,MAAM,EACN,SAAS,EACT,EAAE,SAAS,EAAE,KAAK,EAAE,CACrB,CAAA;QAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAA;IACjE,CAAC;IAED,wCAAwC;IAChC,KAAK,CAAC,cAAc,CAC1B,KAAa;QAEb,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAIlC,+BAA+B,EAAE,YAAY,EAAE,KAAK,CAAC,CAAA;QAExD,OAAO,UAAU,CAAC,OAAO,EAAE,CAAA;IAC7B,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,GAAW,EACX,KAAyB,EACzB,QAAiC,EAAE;QAEnC,MAAM,KAAK,GAAQ,EAAE,CAAA;QAErB,KAAK,IAAI,MAAM,GAAG,CAAC,GAAI,MAAM,IAAI,UAAU,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;YAEpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAE5B,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;YAE5D,KAAK,CAAC,IAAI,CAAC,GAAI,MAAM,CAAC,GAAG,CAAS,CAAC,CAAA;YAEnC,IAAI,MAAM,GAAG,UAAU,IAAI,MAAM,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAA;QACvD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI,CAAI,MAAc,EAAE,GAAG,MAAiB;QACxD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAI,MAAM,EAAE,GAAG,MAAM,CAAC,CAAA;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;gBAAE,MAAM,KAAK,CAAA;YAEjD,MAAM,IAAI,gBAAgB,CACxB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,IAAI,EAAE,MAAM,EAClB,KAAK,CAAC,IAAI,EAAE,OAAO,CACpB,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,SAAS,SAAS,CAAC,QAAmD;IACpE,OAAO,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,aAAa,KAAK,SAAS,CAAA;AAC1E,CAAC"}