@t4h.framework/dev 0.0.0-experimental-20260812130420 → 0.0.0-experimental-20260902161345

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 (170) hide show
  1. package/CHANGELOG.md +63 -4
  2. package/README.md +94 -45
  3. package/dist/AppProcess.d.ts +36 -0
  4. package/dist/AppProcess.js +125 -0
  5. package/dist/AppProcess.js.map +1 -0
  6. package/dist/Server.d.ts +45 -0
  7. package/dist/Server.js +169 -0
  8. package/dist/Server.js.map +1 -0
  9. package/dist/constants/server.d.ts +8 -0
  10. package/dist/constants/server.js +9 -0
  11. package/dist/constants/server.js.map +1 -0
  12. package/dist/http/create-app.d.ts +16 -0
  13. package/dist/http/create-app.js +83 -0
  14. package/dist/http/create-app.js.map +1 -0
  15. package/dist/http/helpers/to-http-error.d.ts +8 -0
  16. package/dist/http/helpers/to-http-error.js +9 -0
  17. package/dist/http/helpers/to-http-error.js.map +1 -0
  18. package/dist/http/middlewares/error-handler.middleware.d.ts +2 -0
  19. package/dist/http/middlewares/error-handler.middleware.js +27 -0
  20. package/dist/http/middlewares/error-handler.middleware.js.map +1 -0
  21. package/dist/http/middlewares/project-manifest.middleware.d.ts +11 -0
  22. package/dist/http/middlewares/project-manifest.middleware.js +11 -0
  23. package/dist/http/middlewares/project-manifest.middleware.js.map +1 -0
  24. package/dist/http/middlewares/read-json-body.middleware.d.ts +6 -0
  25. package/dist/http/middlewares/read-json-body.middleware.js +22 -0
  26. package/dist/http/middlewares/read-json-body.middleware.js.map +1 -0
  27. package/dist/http/middlewares/workflow-authorization.middleware.d.ts +12 -0
  28. package/dist/http/middlewares/workflow-authorization.middleware.js +28 -0
  29. package/dist/http/middlewares/workflow-authorization.middleware.js.map +1 -0
  30. package/dist/index.d.ts +3 -15
  31. package/dist/index.js +2 -15
  32. package/dist/index.js.map +1 -1
  33. package/dist/models/JSONRPCClient.d.ts +2 -0
  34. package/dist/models/JSONRPCClient.js +21 -4
  35. package/dist/models/JSONRPCClient.js.map +1 -1
  36. package/dist/models/JSONRPCError.d.ts +13 -0
  37. package/dist/models/JSONRPCError.js +11 -0
  38. package/dist/models/JSONRPCError.js.map +1 -0
  39. package/dist/models/JSONRPCServer.d.ts +2 -0
  40. package/dist/models/JSONRPCServer.js +27 -5
  41. package/dist/models/JSONRPCServer.js.map +1 -1
  42. package/dist/models/WorkflowAuthorizationMissingError.d.ts +5 -0
  43. package/dist/models/WorkflowAuthorizationMissingError.js +9 -0
  44. package/dist/models/WorkflowAuthorizationMissingError.js.map +1 -0
  45. package/dist/models/WorkflowRun.d.ts +26 -15
  46. package/dist/models/WorkflowRun.js +15 -8
  47. package/dist/models/WorkflowRun.js.map +1 -1
  48. package/dist/models/WorkflowRunActivity.d.ts +37 -27
  49. package/dist/models/WorkflowRunActivity.js +44 -34
  50. package/dist/models/WorkflowRunActivity.js.map +1 -1
  51. package/dist/models/claims/DevFileSystemClaim.d.ts +1 -1
  52. package/dist/models/claims/DevFileSystemClaim.js +2 -2
  53. package/dist/models/claims/DevFileSystemClaim.js.map +1 -1
  54. package/dist/models/claims/DevORMClaim.d.ts +15 -4
  55. package/dist/models/claims/DevORMClaim.js +128 -29
  56. package/dist/models/claims/DevORMClaim.js.map +1 -1
  57. package/dist/models/claims/DevWorkflowBatchClaim.js +2 -3
  58. package/dist/models/claims/DevWorkflowBatchClaim.js.map +1 -1
  59. package/dist/models/claims/DevWorkflowClaim.d.ts +1 -1
  60. package/dist/models/claims/DevWorkflowClaim.js +6 -11
  61. package/dist/models/claims/DevWorkflowClaim.js.map +1 -1
  62. package/dist/repositories/WorkflowRun.repository.d.ts +26 -6
  63. package/dist/repositories/WorkflowRun.repository.js +162 -11
  64. package/dist/repositories/WorkflowRun.repository.js.map +1 -1
  65. package/dist/repositories/WorkflowRunActivity.repository.d.ts +11 -6
  66. package/dist/repositories/WorkflowRunActivity.repository.js +53 -23
  67. package/dist/repositories/WorkflowRunActivity.repository.js.map +1 -1
  68. package/dist/repositories/WorkflowRunAsyncActivityPending.repository.d.ts +26 -0
  69. package/dist/repositories/WorkflowRunAsyncActivityPending.repository.js +120 -0
  70. package/dist/repositories/WorkflowRunAsyncActivityPending.repository.js.map +1 -0
  71. package/dist/services/ActivityRegistry.service.d.ts +7 -0
  72. package/dist/services/ActivityRegistry.service.js +32 -0
  73. package/dist/services/ActivityRegistry.service.js.map +1 -0
  74. package/dist/services/Database.service.d.ts +14 -0
  75. package/dist/services/Database.service.js +106 -0
  76. package/dist/services/Database.service.js.map +1 -0
  77. package/dist/services/TimeoutScheduler.service.js +9 -3
  78. package/dist/services/TimeoutScheduler.service.js.map +1 -1
  79. package/dist/services/WorkflowAuthorization.service.d.ts +19 -0
  80. package/dist/services/WorkflowAuthorization.service.js +75 -0
  81. package/dist/services/WorkflowAuthorization.service.js.map +1 -0
  82. package/dist/services/WorkflowRunAsyncActivityFacade.service.d.ts +8 -15
  83. package/dist/services/WorkflowRunAsyncActivityFacade.service.js +12 -26
  84. package/dist/services/WorkflowRunAsyncActivityFacade.service.js.map +1 -1
  85. package/dist/services/WorkflowRunFacade.service.d.ts +73 -7
  86. package/dist/services/WorkflowRunFacade.service.js +37 -10
  87. package/dist/services/WorkflowRunFacade.service.js.map +1 -1
  88. package/dist/services/WorkflowRunLock.service.d.ts +6 -0
  89. package/dist/services/WorkflowRunLock.service.js +34 -0
  90. package/dist/services/WorkflowRunLock.service.js.map +1 -0
  91. package/dist/services/WorkflowRunSyncActivityFacade.service.d.ts +4 -4
  92. package/dist/services/WorkflowRunSyncActivityFacade.service.js +7 -7
  93. package/dist/services/WorkflowRunSyncActivityFacade.service.js.map +1 -1
  94. package/dist/tools/find-workflow-by-id.d.ts +2 -0
  95. package/dist/tools/find-workflow-by-id.js +9 -0
  96. package/dist/tools/find-workflow-by-id.js.map +1 -0
  97. package/dist/tools/format-routes.d.ts +10 -0
  98. package/dist/tools/format-routes.js +39 -0
  99. package/dist/tools/format-routes.js.map +1 -0
  100. package/dist/tools/replace.d.ts +1 -0
  101. package/dist/tools/replace.js +14 -0
  102. package/dist/tools/replace.js.map +1 -0
  103. package/dist/transport/AppProcessJsonRpc.js +41 -0
  104. package/dist/transport/AppProcessJsonRpc.js.map +1 -0
  105. package/dist/use-cases/BuildWorkflowRunActivityHistory.usecase.d.ts +9 -0
  106. package/dist/use-cases/{WorkflowRunBuildHistory.usecase.js → BuildWorkflowRunActivityHistory.usecase.js} +18 -16
  107. package/dist/use-cases/BuildWorkflowRunActivityHistory.usecase.js.map +1 -0
  108. package/dist/use-cases/CreateWorkflowRun.usecase.d.ts +4 -6
  109. package/dist/use-cases/CreateWorkflowRun.usecase.js +14 -22
  110. package/dist/use-cases/CreateWorkflowRun.usecase.js.map +1 -1
  111. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.d.ts +9 -3
  112. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.js +42 -39
  113. package/dist/use-cases/CreateWorkflowRunAsyncActivity.usecase.js.map +1 -1
  114. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.d.ts +9 -0
  115. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.js +43 -0
  116. package/dist/use-cases/EnqueueWorkflowRunNextTick.usecase.js.map +1 -0
  117. package/dist/use-cases/ExecuteWorkflowRunActivity.usecase.d.ts +9 -0
  118. package/dist/use-cases/ExecuteWorkflowRunActivity.usecase.js +39 -0
  119. package/dist/use-cases/ExecuteWorkflowRunActivity.usecase.js.map +1 -0
  120. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.d.ts +20 -0
  121. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.js +108 -0
  122. package/dist/use-cases/ExecuteWorkflowRunAsyncActivity.usecase.js.map +1 -0
  123. package/dist/use-cases/NextTickWorkflowRun.usecase.d.ts +15 -7
  124. package/dist/use-cases/NextTickWorkflowRun.usecase.js +140 -126
  125. package/dist/use-cases/NextTickWorkflowRun.usecase.js.map +1 -1
  126. package/dist/use-cases/RunWorkflow.usecase.d.ts +10 -0
  127. package/dist/use-cases/RunWorkflow.usecase.js +46 -0
  128. package/dist/use-cases/RunWorkflow.usecase.js.map +1 -0
  129. package/dist/use-cases/WorkflowRunAsyncActivityAdvance.usecase.d.ts +12 -4
  130. package/dist/use-cases/WorkflowRunAsyncActivityAdvance.usecase.js +41 -27
  131. package/dist/use-cases/WorkflowRunAsyncActivityAdvance.usecase.js.map +1 -1
  132. package/dist/use-cases/WorkflowRunFind.usecase.d.ts +32 -0
  133. package/dist/use-cases/WorkflowRunFind.usecase.js +40 -0
  134. package/dist/use-cases/WorkflowRunFind.usecase.js.map +1 -0
  135. package/dist/use-cases/WorkflowRunFindById.usecase.d.ts +53 -0
  136. package/dist/use-cases/WorkflowRunFindById.usecase.js +83 -0
  137. package/dist/use-cases/WorkflowRunFindById.usecase.js.map +1 -0
  138. package/dist/workers/app-process.js +1 -1
  139. package/dist/workers/app-process.js.map +1 -1
  140. package/package.json +16 -7
  141. package/.ai/skills/framework-dev/SKILL.md +0 -348
  142. package/dist/DevServer.d.ts +0 -24
  143. package/dist/DevServer.js +0 -87
  144. package/dist/DevServer.js.map +0 -1
  145. package/dist/models/InMemoryDatabase.d.ts +0 -20
  146. package/dist/models/InMemoryDatabase.js +0 -111
  147. package/dist/models/InMemoryDatabase.js.map +0 -1
  148. package/dist/services/BuildWorkflowRunResult.service.d.ts +0 -8
  149. package/dist/services/BuildWorkflowRunResult.service.js +0 -49
  150. package/dist/services/BuildWorkflowRunResult.service.js.map +0 -1
  151. package/dist/tools/is-workflow-waiting.d.ts +0 -4
  152. package/dist/tools/is-workflow-waiting.js +0 -12
  153. package/dist/tools/is-workflow-waiting.js.map +0 -1
  154. package/dist/transport/DevServerJsonRpc.js +0 -42
  155. package/dist/transport/DevServerJsonRpc.js.map +0 -1
  156. package/dist/use-cases/CallbackWorkflowRunAsyncActivity.usecase.d.ts +0 -14
  157. package/dist/use-cases/CallbackWorkflowRunAsyncActivity.usecase.js +0 -64
  158. package/dist/use-cases/CallbackWorkflowRunAsyncActivity.usecase.js.map +0 -1
  159. package/dist/use-cases/TimeoutWorkflowRunAsyncActivity.usecase.d.ts +0 -8
  160. package/dist/use-cases/TimeoutWorkflowRunAsyncActivity.usecase.js +0 -40
  161. package/dist/use-cases/TimeoutWorkflowRunAsyncActivity.usecase.js.map +0 -1
  162. package/dist/use-cases/WorkflowRunAsyncActivity.usecase.d.ts +0 -7
  163. package/dist/use-cases/WorkflowRunAsyncActivity.usecase.js +0 -46
  164. package/dist/use-cases/WorkflowRunAsyncActivity.usecase.js.map +0 -1
  165. package/dist/use-cases/WorkflowRunBuildHistory.usecase.d.ts +0 -8
  166. package/dist/use-cases/WorkflowRunBuildHistory.usecase.js.map +0 -1
  167. package/dist/use-cases/WorkflowRunSyncActivity.usecase.d.ts +0 -4
  168. package/dist/use-cases/WorkflowRunSyncActivity.usecase.js +0 -28
  169. package/dist/use-cases/WorkflowRunSyncActivity.usecase.js.map +0 -1
  170. /package/dist/transport/{DevServerJsonRpc.d.ts → AppProcessJsonRpc.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,13 +1,72 @@
1
1
  # @t4h.framework/dev
2
2
 
3
- ## 0.0.0-experimental-20260812130420
3
+ ## 0.0.0-experimental-20260902161345
4
+
5
+ ### Minor Changes
6
+
7
+ - [#145](https://github.com/tech4humans-brasil/framework/pull/145) [`13c7a2e`](https://github.com/tech4humans-brasil/framework/commit/13c7a2e80ad5cd3e9ab10ebe5f3cdfc66f4bc664) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Replaces the interactive REPL of `framework dev` with an HTTP dev server: Hono routes workflow (`POST /projects/:projectId/workflows/:workflowId/runs` answers `201 { id }`, `PATCH .../runs/:runId/activities/:activityId` advances a pending async activity), mandatory workflow authorization resolved from the app/workflow `Authorization` manifest, `/_dev` routes for tooling (manifest, runs, waiting activities, env, SSE events) and Vite in middleware mode for a UI. Workflow runs now live in an in-memory SQLite database inside the app process, the ORM dev claim stores its rows in `db.sqlite` instead of rewriting `db.json` on every change, child workflows run in parallel, and `framework dev` gains `--port` (`PORT`) and `--host`. `DevServer` and `isWorkflowWaiting` are gone; use `Server`.
8
+
9
+ ## 0.14.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#143](https://github.com/tech4humans-brasil/framework/pull/143) [`00563fd`](https://github.com/tech4humans-brasil/framework/commit/00563fd9f30cf007a1e5ec8372085cf392d839f4) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Fix start workflow many interruptions
14
+
15
+ ## 0.14.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [`298806e`](https://github.com/tech4humans-brasil/framework/commit/298806ec8f05fecd7d03465627b45236c5d4f8f1) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Points the `@t4h.framework/http` dependency back to the `0.x` line (`^0.4.3`). `0.14.0` was published depending on the accidental `http@1.0.0`.
20
+
21
+ ## 0.14.0
22
+
23
+ ### Minor Changes
24
+
25
+ - [`8c56f76`](https://github.com/tech4humans-brasil/framework/commit/8c56f7697390a1ea966d1e91ff5f35ce5751a0d7) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - feat: write in-memory content to durable storage from a workflow
26
+
27
+ There was no supported way to turn a string or a Buffer into a `Binary` inside
28
+ a workflow — every `Binary` came from an existing file (`http` response,
29
+ `sftp.get`, `split`, `join`). Anyone needing to upload computed content had to
30
+ implement `Binary` by hand, and such an instance can never be persisted, so the
31
+ activity carrying it failed to serialize.
32
+
33
+ `write(content, options?)` covers that gap: it pushes an activity that stores
34
+ the content through the `FileSystemClaim` and returns a `Binary` that survives
35
+ replay.
36
+
37
+ ```ts
38
+ const file = await write(JSON.stringify(data), {
39
+ contentType: 'application/json',
40
+ })
41
+
42
+ await sftp.put('/out/data.json', file)
43
+ ```
44
+
45
+ `FileSystemClaim.write` takes an optional `contentType` — until now the content
46
+ type was always inferred from the file extension.
47
+
48
+ The dev codec no longer diverges from the runtime one: its binary kind used to
49
+ match only `DevFileBinary`, so a hand-written `Binary` was silently serialized
50
+ as a plain object locally and blew up once deployed. It now matches any
51
+ `Binary` and spools unknown ones to disk, the same way the runtime spools them
52
+ to the file storage.
53
+
54
+ - [`8c56f76`](https://github.com/tech4humans-brasil/framework/commit/8c56f7697390a1ea966d1e91ff5f35ce5751a0d7) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Adds FS write activity
55
+
56
+ ### Patch Changes
57
+
58
+ - Updated dependencies [[`8c56f76`](https://github.com/tech4humans-brasil/framework/commit/8c56f7697390a1ea966d1e91ff5f35ce5751a0d7), [`8c56f76`](https://github.com/tech4humans-brasil/framework/commit/8c56f7697390a1ea966d1e91ff5f35ce5751a0d7)]:
59
+ - @t4h.framework/fs@0.8.0
60
+ - @t4h.framework/http@1.0.0
61
+
62
+ ## 0.13.2
4
63
 
5
64
  ### Patch Changes
6
65
 
7
- - [#135](https://github.com/tech4humans-brasil/framework/pull/135) [`f87f69a`](https://github.com/tech4humans-brasil/framework/commit/f87f69a98cf438d7efd4ebcd6c0400acb26dc2bf) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Fix start workflow activity
66
+ - [#135](https://github.com/tech4humans-brasil/framework/pull/135) [`c238dbe`](https://github.com/tech4humans-brasil/framework/commit/c238dbea4199169c935c714442d9e316abd74e20) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Fix start workflow activity
8
67
 
9
- - Updated dependencies [[`f87f69a`](https://github.com/tech4humans-brasil/framework/commit/f87f69a98cf438d7efd4ebcd6c0400acb26dc2bf)]:
10
- - @t4h.framework/core@0.0.0-experimental-20260812130420
68
+ - Updated dependencies [[`c238dbe`](https://github.com/tech4humans-brasil/framework/commit/c238dbea4199169c935c714442d9e316abd74e20)]:
69
+ - @t4h.framework/core@0.9.1
11
70
 
12
71
  ## 0.13.1
13
72
 
package/README.md CHANGED
@@ -1,35 +1,38 @@
1
1
  # @t4h.framework/dev
2
2
 
3
- Local development runtime for [T4H Framework](https://github.com/tech4humans-brasil/framework) apps. Watches your project, compiles TypeScript, loads your `App`, and executes workflows with in-memory claim implementations — no external infrastructure required.
3
+ Local development runtime for [T4H Framework](https://github.com/tech4humans-brasil/framework) apps. Watches your project, compiles TypeScript, loads your `App` in a child process and exposes it over HTTP with the same routes as the production runtime — no external infrastructure required.
4
4
 
5
5
  ## What it does
6
6
 
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`.
11
- 3. **JSON-RPC over IPC** — the parent process drives workflows, env vars, and async activity advancement through a typed RPC layer.
12
- 4. **Dev claims** — provides local implementations for ORM, HTTP, file system, cache, SMTP, and more.
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.
11
+ 3. **HTTP server** — a [Hono](https://hono.dev) app that mirrors the production routes (without the tenant prefix), enforces the workflow authorization and exposes `/_dev` routes for tooling.
12
+ 4. **Vite** — a Vite dev server in middleware mode serves everything that is not an API route, ready for a UI plugin.
13
+ 5. **Dev claims** — provides local implementations for ORM, HTTP, file system, cache, SMTP, and more.
13
14
 
14
15
  ```mermaid
15
16
  flowchart TB
16
- subgraph parent ["Parent process (DevServer)"]
17
+ subgraph parent ["Parent process (Server)"]
17
18
  Watch["TypeScript watch"]
18
- RPCClient["JSON-RPC client"]
19
- Watch -->|"build success"| Fork
20
- Fork["fork()"]
21
- Fork --> RPCClient
19
+ HTTP["Hono (/projects, /_dev)"]
20
+ Vite["Vite middlewares (UI)"]
21
+ Auth["Workflow authorization"]
22
+ Watch -->|"build success"| Fork["AppProcess.up()"]
23
+ HTTP --> Auth
22
24
  end
23
25
 
24
26
  subgraph child ["Child process (app-process worker)"]
25
27
  App["User App"]
26
- RPCServer["JSON-RPC server"]
28
+ Engine["Workflow engine + SQLite :memory:"]
27
29
  Claims["Dev claims"]
28
- App --> RPCServer
30
+ App --> Engine
29
31
  Claims --> App
30
32
  end
31
33
 
32
- RPCClient <-->|"IPC / JSON-RPC"| RPCServer
34
+ Fork --> App
35
+ HTTP <-->|"IPC / JSON-RPC"| Engine
33
36
  ```
34
37
 
35
38
  ## Installation
@@ -76,6 +79,8 @@ Then run:
76
79
  yarn dev
77
80
  ```
78
81
 
82
+ The server listens right away and prints the routes of every workflow once the first build finishes.
83
+
79
84
  ### Options
80
85
 
81
86
  | Flag | Description | Default |
@@ -83,6 +88,8 @@ yarn dev
83
88
  | `--entrypoint <path>` | Path to the project's `package.json` | `./package.json` |
84
89
  | `-e, --env <KEY=VALUE>` | Environment variable (repeatable) | — |
85
90
  | `--env-file-if-exists <path>` | Load variables from a `.env` file if it exists | — |
91
+ | `-p, --port <port>` | HTTP port (also `PORT`) | `3000` |
92
+ | `--host <host>` | HTTP host | `localhost` |
86
93
 
87
94
  Example with env vars:
88
95
 
@@ -90,47 +97,89 @@ Example with env vars:
90
97
  framework dev --entrypoint ./package.json -e API_KEY=secret -e DB_HOST=localhost
91
98
  ```
92
99
 
93
- ## Programmatic usage
100
+ ## HTTP routes
101
+
102
+ The routes are the production ones without the `/tenants/:tenant` and `/versions/:projectVersionId` segments: the dev server has no tenants and a single live version (the last build). `projectId` must match your `App` id.
103
+
104
+ | Method | Route | Authorization | Response |
105
+ |--------|-------|---------------|----------|
106
+ | `GET` | `/projects/:projectId/manifest.json` | no | `200` the app manifest |
107
+ | `POST` | `/projects/:projectId/workflows/:workflowId/runs` | yes | `201 { "id": "<run id>" }` |
108
+ | `PATCH` | `/projects/:projectId/workflows/:workflowId/runs/:runId/activities/:activityId` | yes | `200 { id, type, status }` |
109
+
110
+ The `POST` body is the workflow input, validated against the workflow schema (`400` with the validation errors). The `PATCH` body is `{ "payload": ... }`, validated against the pending async activity schema (`400 Payload is invalid`, `400 AsyncActivity is not pending`). Errors use the NestJS shape `{ statusCode, message, error }`; `503` means the app process is still starting.
111
+
112
+ ```bash
113
+ curl -X POST http://localhost:3000/projects/my-app/workflows/my-workflow/runs \
114
+ -H 'content-type: application/json' \
115
+ -H 'x-signature: <hmac>' \
116
+ -d '{ "userId": "123" }'
117
+ ```
118
+
119
+ ### Authorization
120
+
121
+ Every production-mirror route requires an authorization, exactly like the production runtime: the workflow `authorization` wins over the app one, its manifest `pathToModule` is imported and its default export receives the manifest `context` templated with the request (`<< headers.x-signature >>`, `<< rawBody >>`, `<< body.id >>`, `<< params.projectId >>`, `<< query.token >>`). A falsy result or a thrown error answers `401`. A workflow without any authorization answers `500` on purpose: it will not work in production either.
122
+
123
+ `pathToModule` may be `@t4h.framework/hmac/authorize`, `@t4h.framework/jwks/authorize`, `@t4h.framework/oidc/authorize`, an absolute path, a path relative to the project or a `file://` URL.
124
+
125
+ ### Dev routes (no authorization)
94
126
 
95
- You can embed `DevServer` in your own tooling instead of using the interactive CLI:
127
+ | Method | Route | Description |
128
+ |--------|-------|-------------|
129
+ | `GET` | `/_dev/manifest` | App manifest |
130
+ | `GET` | `/_dev/state` | `{ state: 'idle' \| 'starting' \| 'ready' \| 'exited' }` |
131
+ | `GET` | `/_dev/runs?status=&workflow=&limit=&offset=` | `{ count, runs }` newest first |
132
+ | `GET` | `/_dev/runs/:id` | Run with activities, pendings and logs (framework tagged JSON) |
133
+ | `GET` | `/_dev/activities/waiting` | Async activities waiting for an advance |
134
+ | `GET` | `/_dev/env` | Environment variables of the app process |
135
+ | `PUT` | `/_dev/env/:name` | `{ value }` sets an environment variable |
136
+ | `GET` | `/_dev/events` | SSE: `manifest`, `build:status`, `build:fail`, `app:exit` |
137
+
138
+ Everything else is handed to Vite, so a UI plugin registered in the project's `vite.config.*` (or through `vite.plugins`) is served by the same port.
139
+
140
+ ## State
141
+
142
+ 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. Durability, queues and resume belong to the production runtime.
143
+
144
+ Sync activities run inline, `sleep` and other timers use `setTimeout`, and child workflows started with `startWorkflow` / `startWorkflowMany` run in parallel, like in production.
145
+
146
+ 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.
147
+
148
+ ## Programmatic usage
96
149
 
97
150
  ```typescript
98
- import { DevServer } from '@t4h.framework/dev'
99
-
100
- const devServer = new DevServer(
101
- {
102
- entrypoint: './package.json',
103
- env: { API_KEY: 'secret' },
104
- },
105
- manifest => {
106
- console.log('App loaded:', manifest.workflows.map(w => w.id))
107
- },
108
- )
109
-
110
- await devServer.start()
111
-
112
- const result = await devServer.runWorkflow('my-workflow/v1', {
113
- userId: '123',
114
- amount: 100,
151
+ import { Server } from '@t4h.framework/dev'
152
+
153
+ const server = new Server({
154
+ entrypoint: './package.json',
155
+ env: { API_KEY: 'secret' },
156
+ port: 3000,
157
+ host: 'localhost',
158
+ vite: { plugins: [myPanelPlugin()] },
159
+ })
160
+
161
+ server.on('manifest', manifest => {
162
+ console.log('App ready:', manifest.workflows.map(workflow => workflow.id))
115
163
  })
116
164
 
117
- await devServer.setEnv('API_KEY', 'new-value')
118
- const env = await devServer.listEnv()
165
+ const address = await server.up()
119
166
 
120
- const pending = await devServer.listWaitingAsyncActivities()
121
- await devServer.advanceAsyncActivity(pending[0].id, { approved: true })
167
+ console.log(address.url)
168
+
169
+ await server.down()
122
170
  ```
123
171
 
124
- ### DevServer API
172
+ ### Server API
125
173
 
126
- | Method | Description |
174
+ | Member | Description |
127
175
  |--------|-------------|
128
- | `start()` | Resolves project paths, starts TypeScript watch, and boots the app process on first successful build. |
129
- | `runWorkflow(id, input)` | Runs a workflow by id with the given input. |
130
- | `setEnv(name, value)` | Sets an environment variable in the running app process. |
131
- | `listEnv()` | Returns all environment variables. |
132
- | `listWaitingAsyncActivities()` | Lists async activities waiting for manual advancement. |
133
- | `advanceAsyncActivity(id, payload)` | Advances a pending async activity with the given payload. |
176
+ | `up()` | Starts HTTP + Vite, then the TypeScript watch; resolves with `{ host, port, url }`. |
177
+ | `down()` | Stops the watch, the app process, Vite and the HTTP server. |
178
+ | `manifest` | Current app manifest or `null`. |
179
+ | `address` | Listening address (throws before `up()`). |
180
+ | events | `manifest`, `build:status`, `build:fail`, `app:exit`, `error`. |
181
+
182
+ `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.
134
183
 
135
184
  ## Dev claims
136
185
 
@@ -138,7 +187,7 @@ In production, claims are fulfilled by the runtime (database connections, real H
138
187
 
139
188
  | Claim | Dev implementation |
140
189
  |-------|-------------------|
141
- | `ORMClaim` | In-memory database |
190
+ | `ORMClaim` | SQLite file `db.sqlite` in the project directory; `where` keeps the Mongo-like semantics (`$like`, `$ilike`, `$or`, ...) |
142
191
  | `HttpClientRequestClaim` | Real HTTP via `undici` |
143
192
  | `FileSystemClaim` | Local file system with dev binary codec |
144
193
  | `SmtpSendEmailClaim` | Captures emails in memory (no delivery) |
@@ -164,7 +213,7 @@ import {
164
213
 
165
214
  ## Requirements
166
215
 
167
- - Node.js >= 22
216
+ - Node.js >= 22.13 (`node:sqlite`)
168
217
  - A T4H Framework `App` exported from your project's entry point (`default` or named `app` export)
169
218
 
170
219
  ## License
@@ -0,0 +1,36 @@
1
+ import { fork } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ import type { App } from '@t4h.framework/core';
4
+ export type AppManifest = ReturnType<App['toManifest']>;
5
+ export type AppProcessState = 'idle' | 'starting' | 'ready' | 'exited';
6
+ export declare class AppProcessNotReadyError extends Error {
7
+ readonly name = "AppProcessNotReadyError";
8
+ }
9
+ export interface AppProcessOptions {
10
+ workerPath?: string;
11
+ readyTimeoutInMs?: number;
12
+ killTimeoutInMs?: number;
13
+ fork?: typeof fork;
14
+ }
15
+ export declare class AppProcess extends EventEmitter {
16
+ private readonly workerPath;
17
+ private readonly readyTimeoutInMs;
18
+ private readonly killTimeoutInMs;
19
+ private readonly forkProcess;
20
+ private readonly server;
21
+ private child;
22
+ private client;
23
+ private ready;
24
+ private currentManifest;
25
+ private currentState;
26
+ constructor({ workerPath, readyTimeoutInMs, killTimeoutInMs, fork: forkProcess, }?: AppProcessOptions);
27
+ get manifest(): AppManifest | null;
28
+ get state(): AppProcessState;
29
+ up(entrypoint: string, env: Record<string, string>): Promise<AppManifest>;
30
+ down(): Promise<void>;
31
+ private kill;
32
+ whenReady(): Promise<AppManifest>;
33
+ call<T = any>(method: string, ...params: any[]): Promise<T>;
34
+ private onManifest;
35
+ private onExit;
36
+ }
@@ -0,0 +1,125 @@
1
+ import { fork } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ import path from 'node:path';
4
+ import { styleText } from 'node:util';
5
+ import Type from 'typebox';
6
+ import { APP_KILL_TIMEOUT_IN_MS, APP_READY_TIMEOUT_IN_MS, } from './constants/server.js';
7
+ import { JSONRPCClient } from './models/JSONRPCClient.js';
8
+ import { JSONRPCServer, JSONRPCServerMethod } from './models/JSONRPCServer.js';
9
+ export class AppProcessNotReadyError extends Error {
10
+ name = 'AppProcessNotReadyError';
11
+ }
12
+ export class AppProcess extends EventEmitter {
13
+ workerPath;
14
+ readyTimeoutInMs;
15
+ killTimeoutInMs;
16
+ forkProcess;
17
+ server;
18
+ child = null;
19
+ client = null;
20
+ ready = null;
21
+ currentManifest = null;
22
+ 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, } = {}) {
24
+ super();
25
+ this.workerPath = workerPath;
26
+ this.readyTimeoutInMs = readyTimeoutInMs;
27
+ this.killTimeoutInMs = killTimeoutInMs;
28
+ this.forkProcess = forkProcess;
29
+ this.server = new JSONRPCServer([
30
+ new JSONRPCServerMethod('manifest', { schema: [Type.Any()] }, (manifest) => this.onManifest(manifest)),
31
+ ], message => {
32
+ this.child?.send(message);
33
+ });
34
+ }
35
+ get manifest() {
36
+ return this.currentManifest;
37
+ }
38
+ get state() {
39
+ return this.currentState;
40
+ }
41
+ async up(entrypoint, env) {
42
+ const previous = this.child;
43
+ this.child = null;
44
+ this.client?.rejectPending(new AppProcessNotReadyError('App process is restarting'));
45
+ this.client = null;
46
+ this.ready = Promise.withResolvers();
47
+ this.ready.promise.catch(() => { });
48
+ this.currentState = 'starting';
49
+ await this.kill(previous);
50
+ const child = this.forkProcess(this.workerPath, [
51
+ entrypoint,
52
+ ...Object.entries(env).map(([name, value]) => `${name}=${value}`),
53
+ ], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'] });
54
+ const client = new JSONRPCClient(message => {
55
+ child.send(message);
56
+ });
57
+ this.child = child;
58
+ this.client = client;
59
+ child.on('message', message => Promise.all([this.server.handle(message), client.handle(message)]).catch(error => {
60
+ console.error(styleText('red', '[AppProcess] failed to handle message:', {
61
+ stream: process.stderr,
62
+ }), error);
63
+ }));
64
+ child.on('exit', code => this.onExit(child, code));
65
+ return this.whenReady();
66
+ }
67
+ async down() {
68
+ await this.kill(this.child);
69
+ }
70
+ async kill(child) {
71
+ if (!child)
72
+ return;
73
+ if (child.exitCode !== null || child.signalCode !== null)
74
+ return;
75
+ await new Promise(resolve => {
76
+ const timer = setTimeout(() => child.kill('SIGKILL'), this.killTimeoutInMs);
77
+ child.once('exit', () => {
78
+ clearTimeout(timer);
79
+ resolve();
80
+ });
81
+ child.kill();
82
+ });
83
+ }
84
+ whenReady() {
85
+ if (this.currentState === 'ready' && this.currentManifest)
86
+ return Promise.resolve(this.currentManifest);
87
+ if (this.currentState !== 'starting' || !this.ready)
88
+ return Promise.reject(new AppProcessNotReadyError('App process is not running'));
89
+ const { promise } = this.ready;
90
+ return new Promise((resolve, reject) => {
91
+ const timer = setTimeout(() => reject(new AppProcessNotReadyError(`App process did not become ready in ${this.readyTimeoutInMs}ms`)), this.readyTimeoutInMs);
92
+ promise.then(manifest => {
93
+ clearTimeout(timer);
94
+ resolve(manifest);
95
+ }, error => {
96
+ clearTimeout(timer);
97
+ reject(error);
98
+ });
99
+ });
100
+ }
101
+ async call(method, ...params) {
102
+ await this.whenReady();
103
+ if (!this.client)
104
+ throw new AppProcessNotReadyError('App process is not running');
105
+ return this.client.call(method, ...params);
106
+ }
107
+ onManifest(manifest) {
108
+ this.currentManifest = manifest;
109
+ this.currentState = 'ready';
110
+ this.ready?.resolve(manifest);
111
+ this.emit('manifest', manifest);
112
+ }
113
+ onExit(child, code) {
114
+ if (this.child !== child)
115
+ return;
116
+ const error = new AppProcessNotReadyError(`App process exited with code ${code}`);
117
+ this.child = null;
118
+ this.currentState = 'exited';
119
+ this.client?.rejectPending(error);
120
+ this.client = null;
121
+ this.ready?.reject(error);
122
+ this.emit('exit', code);
123
+ }
124
+ }
125
+ //# sourceMappingURL=AppProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppProcess.js","sourceRoot":"","sources":["../src/AppProcess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { PluginOption } from 'vite';
3
+ import { type AppManifest } from './AppProcess.js';
4
+ export interface ServerViteOptions {
5
+ root?: string;
6
+ configFile?: string | false;
7
+ plugins?: PluginOption[];
8
+ }
9
+ export type ServerLogger = Pick<Console, 'log' | 'error'>;
10
+ export interface ServerOptions {
11
+ entrypoint: string;
12
+ env: Record<string, string>;
13
+ port?: number;
14
+ host?: string;
15
+ vite?: ServerViteOptions | false;
16
+ logger?: ServerLogger | false;
17
+ }
18
+ export interface ServerAddress {
19
+ host: string;
20
+ port: number;
21
+ url: string;
22
+ }
23
+ export declare class Server extends EventEmitter {
24
+ private readonly options;
25
+ private readonly appProcess;
26
+ private readonly logger;
27
+ private routes;
28
+ private tsBuildWatcher;
29
+ private httpServer;
30
+ private vite;
31
+ private currentAddress;
32
+ private packageJsonPath;
33
+ private outDir;
34
+ constructor(options: ServerOptions);
35
+ get manifest(): AppManifest | null;
36
+ get address(): ServerAddress;
37
+ up(): Promise<ServerAddress>;
38
+ down(): Promise<void>;
39
+ private onTsBuildSuccess;
40
+ /**
41
+ * Vite only serves the UI (a panel plugin from the project's vite.config or
42
+ * from `vite.plugins`); the API never goes through it.
43
+ */
44
+ private createVite;
45
+ }