@clusterenvision/ui-framework 1.0.0

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 (193) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/dist/ai-assistant-Db002XYC.d.ts +92 -0
  4. package/dist/ai-assistant-EobSUV70.d.cts +92 -0
  5. package/dist/browser-DnHpnWwE.d.cts +354 -0
  6. package/dist/browser-Dx4oKf5e.d.ts +354 -0
  7. package/dist/browser-signals-07qodpYT.d.cts +66 -0
  8. package/dist/browser-signals-07qodpYT.d.ts +66 -0
  9. package/dist/browser-signals.cjs +32 -0
  10. package/dist/browser-signals.cjs.map +1 -0
  11. package/dist/browser-signals.d.cts +1 -0
  12. package/dist/browser-signals.d.ts +1 -0
  13. package/dist/browser-signals.js +3 -0
  14. package/dist/browser-signals.js.map +1 -0
  15. package/dist/browser.cjs +197 -0
  16. package/dist/browser.cjs.map +1 -0
  17. package/dist/browser.d.cts +13 -0
  18. package/dist/browser.d.ts +13 -0
  19. package/dist/browser.js +12 -0
  20. package/dist/browser.js.map +1 -0
  21. package/dist/chunk-22HQL2Y4.js +568 -0
  22. package/dist/chunk-22HQL2Y4.js.map +1 -0
  23. package/dist/chunk-3ZBRNFEE.js +1525 -0
  24. package/dist/chunk-3ZBRNFEE.js.map +1 -0
  25. package/dist/chunk-4HRORR2Q.js +1953 -0
  26. package/dist/chunk-4HRORR2Q.js.map +1 -0
  27. package/dist/chunk-4L3UXVL5.cjs +68 -0
  28. package/dist/chunk-4L3UXVL5.cjs.map +1 -0
  29. package/dist/chunk-6BYWFGQY.cjs +226 -0
  30. package/dist/chunk-6BYWFGQY.cjs.map +1 -0
  31. package/dist/chunk-7SCIB5HP.js +57 -0
  32. package/dist/chunk-7SCIB5HP.js.map +1 -0
  33. package/dist/chunk-BBAUALNU.js +888 -0
  34. package/dist/chunk-BBAUALNU.js.map +1 -0
  35. package/dist/chunk-CHLDE4JQ.js +715 -0
  36. package/dist/chunk-CHLDE4JQ.js.map +1 -0
  37. package/dist/chunk-CXTAUXLG.cjs +71 -0
  38. package/dist/chunk-CXTAUXLG.cjs.map +1 -0
  39. package/dist/chunk-D2USIT6V.js +121 -0
  40. package/dist/chunk-D2USIT6V.js.map +1 -0
  41. package/dist/chunk-D3H5CGVD.js +36 -0
  42. package/dist/chunk-D3H5CGVD.js.map +1 -0
  43. package/dist/chunk-DQBX75NJ.js +92 -0
  44. package/dist/chunk-DQBX75NJ.js.map +1 -0
  45. package/dist/chunk-DRPG2DFX.js +208 -0
  46. package/dist/chunk-DRPG2DFX.js.map +1 -0
  47. package/dist/chunk-EFOOXCY7.cjs +41 -0
  48. package/dist/chunk-EFOOXCY7.cjs.map +1 -0
  49. package/dist/chunk-FFCZSYC7.cjs +906 -0
  50. package/dist/chunk-FFCZSYC7.cjs.map +1 -0
  51. package/dist/chunk-FNXIYAET.cjs +1593 -0
  52. package/dist/chunk-FNXIYAET.cjs.map +1 -0
  53. package/dist/chunk-I6GNUM3P.cjs +63 -0
  54. package/dist/chunk-I6GNUM3P.cjs.map +1 -0
  55. package/dist/chunk-IHAMVLRY.js +129 -0
  56. package/dist/chunk-IHAMVLRY.js.map +1 -0
  57. package/dist/chunk-IRBUKIRF.cjs +133 -0
  58. package/dist/chunk-IRBUKIRF.cjs.map +1 -0
  59. package/dist/chunk-KPG5HAHK.cjs +97 -0
  60. package/dist/chunk-KPG5HAHK.cjs.map +1 -0
  61. package/dist/chunk-N7Q2ESLG.cjs +130 -0
  62. package/dist/chunk-N7Q2ESLG.cjs.map +1 -0
  63. package/dist/chunk-PFBEIFVS.js +180 -0
  64. package/dist/chunk-PFBEIFVS.js.map +1 -0
  65. package/dist/chunk-PVZVFICK.cjs +318 -0
  66. package/dist/chunk-PVZVFICK.cjs.map +1 -0
  67. package/dist/chunk-Q3KH6HMU.js +305 -0
  68. package/dist/chunk-Q3KH6HMU.js.map +1 -0
  69. package/dist/chunk-QPAAV32J.cjs +1985 -0
  70. package/dist/chunk-QPAAV32J.cjs.map +1 -0
  71. package/dist/chunk-R6XQUMWT.cjs +61 -0
  72. package/dist/chunk-R6XQUMWT.cjs.map +1 -0
  73. package/dist/chunk-SA5UD5B6.js +92 -0
  74. package/dist/chunk-SA5UD5B6.js.map +1 -0
  75. package/dist/chunk-SM35JOYD.cjs +211 -0
  76. package/dist/chunk-SM35JOYD.cjs.map +1 -0
  77. package/dist/chunk-SZQNIMYI.cjs +592 -0
  78. package/dist/chunk-SZQNIMYI.cjs.map +1 -0
  79. package/dist/chunk-T6T7QE4J.js +224 -0
  80. package/dist/chunk-T6T7QE4J.js.map +1 -0
  81. package/dist/chunk-TIF372DZ.js +65 -0
  82. package/dist/chunk-TIF372DZ.js.map +1 -0
  83. package/dist/chunk-V6JCOBGY.js +69 -0
  84. package/dist/chunk-V6JCOBGY.js.map +1 -0
  85. package/dist/chunk-VHUXNDW2.cjs +189 -0
  86. package/dist/chunk-VHUXNDW2.cjs.map +1 -0
  87. package/dist/chunk-W3LNNY3U.cjs +729 -0
  88. package/dist/chunk-W3LNNY3U.cjs.map +1 -0
  89. package/dist/chunk-ZUWSU4OA.js +61 -0
  90. package/dist/chunk-ZUWSU4OA.js.map +1 -0
  91. package/dist/chunk-ZWUA2LPB.cjs +103 -0
  92. package/dist/chunk-ZWUA2LPB.cjs.map +1 -0
  93. package/dist/cli/index.cjs +566 -0
  94. package/dist/cli/index.cjs.map +1 -0
  95. package/dist/cli/index.d.cts +1 -0
  96. package/dist/cli/index.d.ts +1 -0
  97. package/dist/cli/index.js +558 -0
  98. package/dist/cli/index.js.map +1 -0
  99. package/dist/compiler/index.cjs +80 -0
  100. package/dist/compiler/index.cjs.map +1 -0
  101. package/dist/compiler/index.d.cts +130 -0
  102. package/dist/compiler/index.d.ts +130 -0
  103. package/dist/compiler/index.js +3 -0
  104. package/dist/compiler/index.js.map +1 -0
  105. package/dist/component-BVzvepw9.d.cts +90 -0
  106. package/dist/component-wTxZ2BPD.d.ts +90 -0
  107. package/dist/index-CpxDa60m.d.cts +644 -0
  108. package/dist/index-CpxDa60m.d.ts +644 -0
  109. package/dist/index.cjs +1356 -0
  110. package/dist/index.cjs.map +1 -0
  111. package/dist/index.d.cts +165 -0
  112. package/dist/index.d.ts +165 -0
  113. package/dist/index.js +772 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/lib/dom.cjs +102 -0
  116. package/dist/lib/dom.cjs.map +1 -0
  117. package/dist/lib/dom.d.cts +373 -0
  118. package/dist/lib/dom.d.ts +373 -0
  119. package/dist/lib/dom.js +3 -0
  120. package/dist/lib/dom.js.map +1 -0
  121. package/dist/lib/icons.cjs +20 -0
  122. package/dist/lib/icons.cjs.map +1 -0
  123. package/dist/lib/icons.d.cts +64 -0
  124. package/dist/lib/icons.d.ts +64 -0
  125. package/dist/lib/icons.js +3 -0
  126. package/dist/lib/icons.js.map +1 -0
  127. package/dist/lib/index.cjs +247 -0
  128. package/dist/lib/index.cjs.map +1 -0
  129. package/dist/lib/index.d.cts +30 -0
  130. package/dist/lib/index.d.ts +30 -0
  131. package/dist/lib/index.js +92 -0
  132. package/dist/lib/index.js.map +1 -0
  133. package/dist/lib/theme.cjs +56 -0
  134. package/dist/lib/theme.cjs.map +1 -0
  135. package/dist/lib/theme.d.cts +27 -0
  136. package/dist/lib/theme.d.ts +27 -0
  137. package/dist/lib/theme.js +3 -0
  138. package/dist/lib/theme.js.map +1 -0
  139. package/dist/router-B9kms5XQ.d.ts +124 -0
  140. package/dist/router-YnpW_sIK.d.cts +124 -0
  141. package/dist/runtime/adapters/angular.cjs +48 -0
  142. package/dist/runtime/adapters/angular.cjs.map +1 -0
  143. package/dist/runtime/adapters/angular.d.cts +38 -0
  144. package/dist/runtime/adapters/angular.d.ts +38 -0
  145. package/dist/runtime/adapters/angular.js +46 -0
  146. package/dist/runtime/adapters/angular.js.map +1 -0
  147. package/dist/runtime/adapters/react.cjs +41 -0
  148. package/dist/runtime/adapters/react.cjs.map +1 -0
  149. package/dist/runtime/adapters/react.d.cts +26 -0
  150. package/dist/runtime/adapters/react.d.ts +26 -0
  151. package/dist/runtime/adapters/react.js +39 -0
  152. package/dist/runtime/adapters/react.js.map +1 -0
  153. package/dist/runtime/adapters/vue.cjs +44 -0
  154. package/dist/runtime/adapters/vue.cjs.map +1 -0
  155. package/dist/runtime/adapters/vue.d.cts +37 -0
  156. package/dist/runtime/adapters/vue.d.ts +37 -0
  157. package/dist/runtime/adapters/vue.js +42 -0
  158. package/dist/runtime/adapters/vue.js.map +1 -0
  159. package/dist/runtime/components/ai-assistant.cjs +18 -0
  160. package/dist/runtime/components/ai-assistant.cjs.map +1 -0
  161. package/dist/runtime/components/ai-assistant.d.cts +8 -0
  162. package/dist/runtime/components/ai-assistant.d.ts +8 -0
  163. package/dist/runtime/components/ai-assistant.js +9 -0
  164. package/dist/runtime/components/ai-assistant.js.map +1 -0
  165. package/dist/runtime/components/ai-summary-card.cjs +18 -0
  166. package/dist/runtime/components/ai-summary-card.cjs.map +1 -0
  167. package/dist/runtime/components/ai-summary-card.d.cts +19 -0
  168. package/dist/runtime/components/ai-summary-card.d.ts +19 -0
  169. package/dist/runtime/components/ai-summary-card.js +9 -0
  170. package/dist/runtime/components/ai-summary-card.js.map +1 -0
  171. package/dist/runtime/router.cjs +429 -0
  172. package/dist/runtime/router.cjs.map +1 -0
  173. package/dist/runtime/router.d.cts +2 -0
  174. package/dist/runtime/router.d.ts +2 -0
  175. package/dist/runtime/router.js +421 -0
  176. package/dist/runtime/router.js.map +1 -0
  177. package/dist/runtime/server.cjs +125 -0
  178. package/dist/runtime/server.cjs.map +1 -0
  179. package/dist/runtime/server.d.cts +27 -0
  180. package/dist/runtime/server.d.ts +27 -0
  181. package/dist/runtime/server.js +117 -0
  182. package/dist/runtime/server.js.map +1 -0
  183. package/dist/runtime/workflow/index.cjs +282 -0
  184. package/dist/runtime/workflow/index.cjs.map +1 -0
  185. package/dist/runtime/workflow/index.d.cts +1 -0
  186. package/dist/runtime/workflow/index.d.ts +1 -0
  187. package/dist/runtime/workflow/index.js +5 -0
  188. package/dist/runtime/workflow/index.js.map +1 -0
  189. package/dist/tracing-DGdvMCEl.d.cts +109 -0
  190. package/dist/tracing-DGdvMCEl.d.ts +109 -0
  191. package/dist/types-C4RXXKfk.d.cts +76 -0
  192. package/dist/types-C4RXXKfk.d.ts +76 -0
  193. package/package.json +166 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cluster Envision
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # @clusterenvision/ui-framework
2
+
3
+ A compile-time focused UI framework that powers the CE ecosystem. It blends a component + hooks mental model with Angular-like templates, dependency injection, SSR, and hydration – all optimized through a tiny runtime built on signals.
4
+
5
+ > Looking for a working example? The `web/ce-lms` starter uses `ce-ui-scss`, pre-registers CE web components, and is Vite-ready for dropping `@clusterenvision/ui-framework` components into a realistic auth flow.
6
+
7
+ ## Highlights
8
+
9
+ - **CEX single-file components** compiled into optimal DOM instructions.
10
+ - **Signals + hooks** for state, side-effects, async resources, and context.
11
+ - **Hierarchical DI + router + forms** out of the box.
12
+ - **Universal rendering**: render the same component on the server and hydrate on the client.
13
+ - **Tooling**: Vite plugin, tsup build, CLI (`ceui`) for compilation pipelines.
14
+
15
+ ## Styling + component alignment
16
+
17
+ This framework expects CE design tokens and web components to be present for a production experience:
18
+
19
+ - **Tokens (scss 1.94.2)**: import `@clusterenvision/ce-ui-scss/dist/ce-ui.css` into your app shell or bundler entry, or use the CDN `https://unpkg.com/@clusterenvision/ce-ui-scss@1.94.2/dist/ce-ui.css` with SRI. Apply a theme class on `<html>` (e.g., `theme-default`, `theme-dark`).
20
+ - **Web Components (1.1.0)**: register CE elements once at startup:
21
+ ```ts
22
+ import { registerDefaultComponents } from '@clusterenvision/ui-webcomponents';
23
+ import '@clusterenvision/ce-ui-scss/dist/ce-ui.css';
24
+
25
+ registerDefaultComponents(); // defines <ce-switch>, <ce-dialog>, etc.
26
+ ```
27
+ - **CEX + CE WC interop**: CEX templates can render CE web components directly (no wrapper). See `examples/webcomponents-bridge` and the integration test under `tests/runtime/webcomponents-interop.spec.ts`.
28
+
29
+ Production hardening: see `docs/PRODUCTION.md` for routing/data/error policies, security headers/CSP, perf budgets, and deployment playbooks. TL;DR for releases: run `npm run lint && npm run test:ci && npm run typecheck && npm run build && npm run bench`, apply CSP and boundary policies per route, and publish only from CI.
30
+
31
+ ## Stack roadmap
32
+
33
+ For the unified future work plan across `ce-ui-framework`, `ce-ui-webcomponents`, `ce-ui-scss`, `ce-ui-kit`, and `ce-ui-platform`, see `docs/ce-ui-framework/STACK_ROADMAP.md`.
34
+
35
+ ## Runtime Requirements
36
+
37
+ - Node.js 20.x LTS (or Node 22.x once the upstream worker leak in Node 25 is fixed). Running the Vitest suite or the CLI on Node 25 currently crashes with `ERR_WORKER_OUT_OF_MEMORY`. Use a version manager such as `nvm`/`fnm` to pin Node 20 when contributing.
38
+
39
+ ## Getting Started
40
+
41
+ ```bash
42
+ npm install
43
+ npm run build
44
+ npx ceui compile examples/basic-counter
45
+ ```
46
+
47
+ Author components with `defineComponent`:
48
+
49
+ ```ts
50
+ import { defineComponent, signal } from '@clusterenvision/ui-framework';
51
+
52
+ export const Counter = defineComponent({
53
+ name: 'Counter',
54
+ template: `
55
+ <section class="counter">
56
+ <h1>Hello {{ props.name }}</h1>
57
+ <button on:click="increment">Clicks {{ count() }}</button>
58
+ <p ce:if="count() > 5">Milestone reached!</p>
59
+ </section>
60
+ `,
61
+ setup() {
62
+ const count = signal(0);
63
+ const increment = () => count.update(v => v + 1);
64
+ return { count, increment };
65
+ }
66
+ });
67
+ ```
68
+
69
+ Then render or hydrate:
70
+
71
+ ```ts
72
+ import { render } from '@clusterenvision/ui-framework';
73
+
74
+ render(Counter, { name: 'CE' }, document.getElementById('app')!);
75
+ ```
76
+
77
+ ### Compiler & parser utilities
78
+
79
+ If you previously depended on `node-html-parser` to preprocess CE templates, you can now import the built-in parser directly from the compiler bundle:
80
+
81
+ ```ts
82
+ import {
83
+ parse,
84
+ createElement,
85
+ createTextNode,
86
+ createCommentNode,
87
+ createFragment,
88
+ serialize,
89
+ walk,
90
+ isElementNode,
91
+ } from '@clusterenvision/ui-framework/compiler';
92
+
93
+ const ast = parse('<section ce:if="visible">Hello</section>', {
94
+ lowerCaseTagName: false,
95
+ lowerCaseAttributeName: false,
96
+ });
97
+
98
+ const fragment = createFragment([createElement('aside'), createTextNode('scoped docs')]);
99
+ fragment.firstChild?.appendChild(createCommentNode('inline note'));
100
+
101
+ const html = serialize([ast, fragment], { pretty: true });
102
+
103
+ walk(ast, (node) => {
104
+ if (isElementNode(node)) {
105
+ console.log('tag', node.tagName, node.attrs);
106
+ }
107
+ return undefined;
108
+ });
109
+ ```
110
+
111
+ This keeps template tooling in sync with the CE compiler and avoids CommonJS bundles when shipping to Angular, React, or Vite-based demos.
112
+
113
+ ### Parser capabilities
114
+
115
+ - Returns a real `DocumentFragment` so multiple root nodes are naturally supported.
116
+ - Configurable tag + attribute casing (`lowerCaseTagName`, `lowerCaseAttributeName`).
117
+ - Optional HTML entity decoding (`decodeEntities`) and comment preservation (`preserveComments`).
118
+ - Overridable `voidElements` / `rawTextElements` for custom syntaxes.
119
+ - Helper factories (`createElement`, `createTextNode`, `createCommentNode`, `createFragment`) plus `cloneNode`, `serialize`, and `walk` for AST transforms.
120
+ - Type guards (`isElementNode`, `isTextNode`, `isCommentNode`, `isParentNode`) ensure ergonomic authoring in toolchains.
121
+
122
+ ## Project Scripts
123
+
124
+ - `npm run build` – bundle via tsup.
125
+ - `npm run dev` – watch mode for hack-and-learn.
126
+ - `npm run test` – Vitest suite for compiler/runtime primitives.
127
+ - `npm run lint` – ESLint (strict TS config).
128
+
129
+ ## CLI
130
+
131
+ The `ceui compile` command now supports incremental workflows:
132
+
133
+ - `ceui compile src/components/**/*.cex --out-dir dist --watch` – recompile on file changes.
134
+ - `--source-map` – emit ESM modules with `.map` files for debugger parity.
135
+ - Scoped `<style>` blocks automatically receive deterministic `data-ce-scope` attributes so emitted CSS stays encapsulated.
136
+
137
+ ## Workflow Orchestrator (Preview)
138
+
139
+ The runtime now exposes a hybrid workflow/state-machine engine that runs in both the browser and Node.js. Author definitions via the fluent builder API or load JSON specs, then execute them with pluggable stores, HTTP/database tasks, actor-aware approvals, and retry policies.
140
+
141
+ ```ts
142
+ import {
143
+ WorkflowRuntime,
144
+ InMemoryWorkflowStore,
145
+ InMemoryDatabaseRegistry,
146
+ createWorkflow,
147
+ httpTask,
148
+ databaseTask,
149
+ createDefaultTaskMap,
150
+ createPostgresProvider,
151
+ DatabaseWorkflowStore
152
+ } from '@clusterenvision/ui-framework/workflow';
153
+
154
+ const definition = createWorkflow('order-fulfillment', builder => {
155
+ builder
156
+ .step('fetch-inventory', httpTask({ url: 'https://inventory.ce/api/items', parse: 'json', assignResponseTo: 'inventory' }))
157
+ .onSuccess('persist-order');
158
+
159
+ builder
160
+ .step('persist-order', databaseTask({
161
+ provider: 'postgres',
162
+ operation: { type: 'command', text: 'select create_order($1)', parameters: [{ $ref: 'inventory' }] },
163
+ assignResultTo: 'order'
164
+ }))
165
+ .withApproval({ id: 'finance', requiredRoles: ['finance-approver'] });
166
+ });
167
+
168
+ const databaseRegistry = new InMemoryDatabaseRegistry();
169
+ const postgresProvider = createPostgresProvider(pool, 'postgres');
170
+ databaseRegistry.register(postgresProvider);
171
+
172
+ const runtime = new WorkflowRuntime({
173
+ store: new DatabaseWorkflowStore({ provider: postgresProvider, dialect: 'postgres' }),
174
+ services: { databases: databaseRegistry },
175
+ tasks: createDefaultTaskMap()
176
+ });
177
+
178
+ await runtime.run(definition, { actor: { id: 'user-123', roles: ['finance-approver'] } });
179
+ ```
180
+
181
+ Highlights:
182
+
183
+ - Hybrid definitions (TypeScript DSL + JSON) with deterministic IDs and metadata.
184
+ - Built-in retry policies, approval gates, and execution history persistence.
185
+ - HTTP + database task adapters (MySQL, Postgres, SQLite, Mongo, or any custom provider).
186
+ - In-memory workflow store, logger, background runner, and time service ready for production swaps.
187
+ - Actor-aware approvals with `actor` context injection and role/approver checks.
188
+ - Delay/schedule helpers (`delayTask`, `scheduleTask`) that leverage the time service, scheduler, and background runner.
189
+
190
+ ### Actor Context & Approval Gates
191
+
192
+ Pass an `actor` into `runtime.run` to capture the human/system identity that initiated a workflow. Steps can call `.withApproval({ id: 'finance', requiredRoles: ['finance-approver'] })` to block until an approver with the appropriate role resolves the gate. Provide a custom `ApprovalResolver` to plug in ticketing/notification flows or multi-step approvals.
193
+
194
+ ### Scheduling & Background Tasks
195
+
196
+ The default services include a scheduler built on the background runner + time service. Use the provided tasks to pause or defer work:
197
+
198
+ ```ts
199
+ builder.step('wait-for-window', delayTask({ seconds: 30 })).onSuccess('notify');
200
+
201
+ builder.step(
202
+ 'notify',
203
+ scheduleTask({ taskName: 'webhook.dispatch', delayMs: 5_000, payload: { target: 'https://hooks.ce/api' } })
204
+ );
205
+ ```
206
+
207
+ You can also inject your own `scheduler` implementation to route deferrals to hosted cron/queue systems.
208
+
209
+ ### Persistence
210
+
211
+ `DatabaseWorkflowStore` serializes workflow state/history into a SQL table (`workflow_instances` by default) using upserts compatible with Postgres, MySQL, and SQLite. The expected schema is:
212
+
213
+ ```sql
214
+ CREATE TABLE workflow_instances (
215
+ id TEXT PRIMARY KEY,
216
+ workflow_id TEXT NOT NULL,
217
+ version TEXT NOT NULL,
218
+ status TEXT NOT NULL,
219
+ current_step TEXT NULL,
220
+ state_json JSON NOT NULL,
221
+ actor_json JSON NULL,
222
+ metadata_json JSON NULL,
223
+ history_json JSON NOT NULL,
224
+ created_at TEXT NOT NULL,
225
+ updated_at TEXT NOT NULL
226
+ );
227
+ ```
228
+
229
+ Swap in a custom store if you need to target MongoDB or document databases directly.
230
+
231
+ #### Mongo Store
232
+
233
+ ```ts
234
+ import { MongoWorkflowStore } from '@clusterenvision/ui-framework/workflow';
235
+
236
+ const mongoStore = new MongoWorkflowStore({ collection: db.collection('workflow_instances'), createIndexes: true });
237
+ const runtime = new WorkflowRuntime({
238
+ store: mongoStore,
239
+ services: { databases: databaseRegistry },
240
+ tasks: createDefaultTaskMap(),
241
+ });
242
+ ```
243
+
244
+ Documents stay shape-aligned with the SQL table (state/history serialized as JSON, indexes on `workflowId`, `status`, `updatedAt`).
245
+
246
+ ### Visual DSL Hooks
247
+
248
+ `workflow/schema.ts` exposes a `VisualWorkflowSchema` with node positions, annotations, and stable IDs so an editor (VS Code, diagram tool, BPMN canvas) can round-trip definitions.
249
+
250
+ ```ts
251
+ import { workflowToVisualSchema, visualSchemaToWorkflow } from '@clusterenvision/ui-framework/workflow';
252
+
253
+ const schema = workflowToVisualSchema(definition);
254
+ schema.nodes[0].position = { x: 100, y: 240 };
255
+ const updatedDefinition = visualSchemaToWorkflow(schema);
256
+ ```
257
+
258
+ ### Database Adapters
259
+
260
+ Beyond the built-in SQL + Mongo helpers, you can now register:
261
+
262
+ - `createPrismaProvider` – wraps Prisma clients via `$queryRawUnsafe` / `$executeRawUnsafe`.
263
+ - `createDrizzleProvider` – forwards to Drizzle’s `execute` API.
264
+ - `createSupabaseProvider` – targets Supabase/PostgREST tables or RPC endpoints.
265
+ - `createRestDatabaseProvider` – generic wrapper over any REST backend (e.g., Hasura, custom serverless DB).
266
+
267
+ ### Queue-Based Background Runners
268
+
269
+ `QueueBackgroundRunner` wires the workflow scheduler to queue systems (BullMQ/Redis, AWS SQS, Azure Storage Queues, or any custom driver). Each driver implements the minimal `QueueDriver` interface so you can plug in enterprise transports while emitting metrics.
270
+
271
+ ```ts
272
+ import { QueueBackgroundRunner, createBullMqDriver, MetricsConsoleEmitter } from '@clusterenvision/ui-framework/workflow';
273
+
274
+ const queueRunner = new QueueBackgroundRunner({
275
+ driver: createBullMqDriver(queue),
276
+ metrics: new MetricsConsoleEmitter(),
277
+ });
278
+
279
+ const runtime = new WorkflowRuntime({
280
+ store: mongoStore,
281
+ services: { background: queueRunner, scheduler: queueRunner },
282
+ tasks: createDefaultTaskMap(),
283
+ });
284
+ ```
285
+
286
+ ### Auth & Policy Integrations
287
+
288
+ - `actorFromAuth0Claims`, `actorFromCognitoClaims`, `actorFromAzureAdClaims`, `actorFromOidcClaims` map identity tokens into `ActorContext`.
289
+ - `PolicyApprovalResolver` + `RuleBasedPolicyEngine` enable custom policy-as-code enforcement before approvals.
290
+ - Middleware helpers (`requireActorRoles`, `requireActorScopes`, `runAuthMiddleware`) make it easy to guard workflow start or per-step execution.
291
+ - `multiStepApprovalResolver` composes multiple resolvers and `ManualOverrideApprovalResolver` allows humans to unblock via manual overrides.
292
+
293
+ ## Status
294
+
295
+ Early alpha. The current codebase focuses on the core runtime, compiler skeleton, CLI, and reference examples. Contributions welcome!
@@ -0,0 +1,92 @@
1
+ import { C as ComponentFactory } from './component-wTxZ2BPD.js';
2
+ import { S as SignalAccessor } from './browser-signals-07qodpYT.js';
3
+
4
+ type AiRole = 'system' | 'user' | 'assistant' | 'tool';
5
+ interface AiMessage {
6
+ id: string;
7
+ role: AiRole;
8
+ content: string;
9
+ createdAt: number;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ interface AiCompletionRequest {
13
+ messages: AiMessage[];
14
+ prompt: string;
15
+ locale?: string;
16
+ context?: Record<string, unknown>;
17
+ }
18
+ interface AiCompletionResponse {
19
+ message: Partial<Omit<AiMessage, 'content'>> & Pick<AiMessage, 'content'>;
20
+ suggestions?: string[];
21
+ usage?: {
22
+ inputTokens?: number;
23
+ outputTokens?: number;
24
+ totalTokens?: number;
25
+ };
26
+ }
27
+ type AiCompletionProvider = (request: AiCompletionRequest) => Promise<AiCompletionResponse>;
28
+ type AiSessionStatus = 'idle' | 'processing' | 'error';
29
+ interface AiSessionOptions {
30
+ provider: AiCompletionProvider;
31
+ initialMessages?: AiMessage[];
32
+ initialSuggestions?: string[];
33
+ locale?: string;
34
+ context?: Record<string, unknown>;
35
+ historyLimit?: number;
36
+ }
37
+ interface AiSessionSendOptions {
38
+ context?: Record<string, unknown>;
39
+ locale?: string;
40
+ systemPrompt?: string;
41
+ }
42
+ interface AiSession {
43
+ messages: SignalAccessor<AiMessage[]>;
44
+ suggestions: SignalAccessor<string[]>;
45
+ status: SignalAccessor<AiSessionStatus>;
46
+ error: SignalAccessor<string | null>;
47
+ send(prompt: string, options?: AiSessionSendOptions): Promise<void>;
48
+ reset(): void;
49
+ }
50
+ declare function createAiSession(options: AiSessionOptions): AiSession;
51
+ interface HttpAiProviderOptions {
52
+ endpoint: string;
53
+ headers?: Record<string, string>;
54
+ fetch?: FetchLike;
55
+ mapResponse?: (payload: unknown) => AiCompletionResponse;
56
+ }
57
+ type FetchLike = (url: string, init?: FetchLikeRequestInit) => Promise<FetchLikeResponse>;
58
+ interface FetchLikeRequestInit {
59
+ method?: string;
60
+ headers?: Record<string, string>;
61
+ body?: string;
62
+ }
63
+ interface FetchLikeResponse {
64
+ ok: boolean;
65
+ status: number;
66
+ json(): Promise<unknown>;
67
+ text(): Promise<string>;
68
+ }
69
+ declare function createHttpAiProvider(options: HttpAiProviderOptions): AiCompletionProvider;
70
+ interface MockAiProviderOptions {
71
+ suggestions?: string[];
72
+ delayMs?: number;
73
+ signature?: string;
74
+ }
75
+ declare function createMockAiProvider(options?: MockAiProviderOptions): AiCompletionProvider;
76
+
77
+ interface AiAssistantPanelProps extends Record<string, unknown> {
78
+ title?: string;
79
+ description?: string;
80
+ messages: AiMessage[];
81
+ suggestions?: string[];
82
+ status?: AiSessionStatus;
83
+ error?: string | null;
84
+ placeholder?: string;
85
+ sendLabel?: string;
86
+ resetLabel?: string;
87
+ busyLabel?: string;
88
+ disabled?: boolean;
89
+ }
90
+ declare const AiAssistantPanel: ComponentFactory<AiAssistantPanelProps>;
91
+
92
+ export { AiAssistantPanel as A, type FetchLike as F, type HttpAiProviderOptions as H, type MockAiProviderOptions as M, type AiAssistantPanelProps as a, type AiCompletionProvider as b, type AiCompletionRequest as c, type AiCompletionResponse as d, type AiMessage as e, type AiRole as f, type AiSession as g, type AiSessionOptions as h, type AiSessionSendOptions as i, type AiSessionStatus as j, type FetchLikeRequestInit as k, type FetchLikeResponse as l, createAiSession as m, createHttpAiProvider as n, createMockAiProvider as o };
@@ -0,0 +1,92 @@
1
+ import { C as ComponentFactory } from './component-BVzvepw9.cjs';
2
+ import { S as SignalAccessor } from './browser-signals-07qodpYT.cjs';
3
+
4
+ type AiRole = 'system' | 'user' | 'assistant' | 'tool';
5
+ interface AiMessage {
6
+ id: string;
7
+ role: AiRole;
8
+ content: string;
9
+ createdAt: number;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ interface AiCompletionRequest {
13
+ messages: AiMessage[];
14
+ prompt: string;
15
+ locale?: string;
16
+ context?: Record<string, unknown>;
17
+ }
18
+ interface AiCompletionResponse {
19
+ message: Partial<Omit<AiMessage, 'content'>> & Pick<AiMessage, 'content'>;
20
+ suggestions?: string[];
21
+ usage?: {
22
+ inputTokens?: number;
23
+ outputTokens?: number;
24
+ totalTokens?: number;
25
+ };
26
+ }
27
+ type AiCompletionProvider = (request: AiCompletionRequest) => Promise<AiCompletionResponse>;
28
+ type AiSessionStatus = 'idle' | 'processing' | 'error';
29
+ interface AiSessionOptions {
30
+ provider: AiCompletionProvider;
31
+ initialMessages?: AiMessage[];
32
+ initialSuggestions?: string[];
33
+ locale?: string;
34
+ context?: Record<string, unknown>;
35
+ historyLimit?: number;
36
+ }
37
+ interface AiSessionSendOptions {
38
+ context?: Record<string, unknown>;
39
+ locale?: string;
40
+ systemPrompt?: string;
41
+ }
42
+ interface AiSession {
43
+ messages: SignalAccessor<AiMessage[]>;
44
+ suggestions: SignalAccessor<string[]>;
45
+ status: SignalAccessor<AiSessionStatus>;
46
+ error: SignalAccessor<string | null>;
47
+ send(prompt: string, options?: AiSessionSendOptions): Promise<void>;
48
+ reset(): void;
49
+ }
50
+ declare function createAiSession(options: AiSessionOptions): AiSession;
51
+ interface HttpAiProviderOptions {
52
+ endpoint: string;
53
+ headers?: Record<string, string>;
54
+ fetch?: FetchLike;
55
+ mapResponse?: (payload: unknown) => AiCompletionResponse;
56
+ }
57
+ type FetchLike = (url: string, init?: FetchLikeRequestInit) => Promise<FetchLikeResponse>;
58
+ interface FetchLikeRequestInit {
59
+ method?: string;
60
+ headers?: Record<string, string>;
61
+ body?: string;
62
+ }
63
+ interface FetchLikeResponse {
64
+ ok: boolean;
65
+ status: number;
66
+ json(): Promise<unknown>;
67
+ text(): Promise<string>;
68
+ }
69
+ declare function createHttpAiProvider(options: HttpAiProviderOptions): AiCompletionProvider;
70
+ interface MockAiProviderOptions {
71
+ suggestions?: string[];
72
+ delayMs?: number;
73
+ signature?: string;
74
+ }
75
+ declare function createMockAiProvider(options?: MockAiProviderOptions): AiCompletionProvider;
76
+
77
+ interface AiAssistantPanelProps extends Record<string, unknown> {
78
+ title?: string;
79
+ description?: string;
80
+ messages: AiMessage[];
81
+ suggestions?: string[];
82
+ status?: AiSessionStatus;
83
+ error?: string | null;
84
+ placeholder?: string;
85
+ sendLabel?: string;
86
+ resetLabel?: string;
87
+ busyLabel?: string;
88
+ disabled?: boolean;
89
+ }
90
+ declare const AiAssistantPanel: ComponentFactory<AiAssistantPanelProps>;
91
+
92
+ export { AiAssistantPanel as A, type FetchLike as F, type HttpAiProviderOptions as H, type MockAiProviderOptions as M, type AiAssistantPanelProps as a, type AiCompletionProvider as b, type AiCompletionRequest as c, type AiCompletionResponse as d, type AiMessage as e, type AiRole as f, type AiSession as g, type AiSessionOptions as h, type AiSessionSendOptions as i, type AiSessionStatus as j, type FetchLikeRequestInit as k, type FetchLikeResponse as l, createAiSession as m, createHttpAiProvider as n, createMockAiProvider as o };