@cadenza.io/service 2.18.3 → 2.19.1
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.
- package/README.md +258 -0
- package/dist/Cadenza-DCMs7q97.d.mts +1666 -0
- package/dist/Cadenza-DCMs7q97.d.ts +1666 -0
- package/dist/browser/chunk-4XOTT2KM.mjs +31 -0
- package/dist/browser/chunk-4XOTT2KM.mjs.map +1 -0
- package/dist/browser/index.js +12256 -4810
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +14687 -7257
- package/dist/browser/index.mjs.map +1 -1
- package/dist/browser/nuxt/index.js +166 -0
- package/dist/browser/nuxt/index.js.map +1 -0
- package/dist/browser/nuxt/index.mjs +121 -0
- package/dist/browser/nuxt/index.mjs.map +1 -0
- package/dist/browser/react/index.js +179 -0
- package/dist/browser/react/index.js.map +1 -0
- package/dist/browser/react/index.mjs +140 -0
- package/dist/browser/react/index.mjs.map +1 -0
- package/dist/browser/vue/index.js +178 -0
- package/dist/browser/vue/index.js.map +1 -0
- package/dist/browser/vue/index.mjs +140 -0
- package/dist/browser/vue/index.mjs.map +1 -0
- package/dist/chunk-DBCS4XXY.mjs +31 -0
- package/dist/chunk-DBCS4XXY.mjs.map +1 -0
- package/dist/index.d.mts +244 -22953
- package/dist/index.d.ts +244 -22953
- package/dist/index.js +19425 -10960
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19308 -10894
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt/index.d.mts +42 -0
- package/dist/nuxt/index.d.ts +42 -0
- package/dist/nuxt/index.js +173 -0
- package/dist/nuxt/index.js.map +1 -0
- package/dist/nuxt/index.mjs +121 -0
- package/dist/nuxt/index.mjs.map +1 -0
- package/dist/react/index.d.mts +52 -0
- package/dist/react/index.d.ts +52 -0
- package/dist/react/index.js +188 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +140 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/runtimeProjectionState-CitON2P3.d.mts +6 -0
- package/dist/runtimeProjectionState-CitON2P3.d.ts +6 -0
- package/dist/vue/index.d.mts +48 -0
- package/dist/vue/index.d.ts +48 -0
- package/dist/vue/index.js +187 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/index.mjs +140 -0
- package/dist/vue/index.mjs.map +1 -0
- package/package.json +62 -6
package/README.md
CHANGED
|
@@ -63,6 +63,264 @@ Frontend bootstrap resolution order is:
|
|
|
63
63
|
|
|
64
64
|
`CADENZA_DB_ADDRESS` now accepts either a full address with port, or a bare host/address when `CADENZA_DB_PORT` is also set.
|
|
65
65
|
|
|
66
|
+
### Creating a browser runtime actor
|
|
67
|
+
If you want a reusable browser runtime primitive on top of frontend mode, use `createBrowserRuntimeActor(...)`. This keeps the shared runtime framework agnostic and lets Vue/Nuxt, React, or other frontend adapters subscribe to plain runtime state updates.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import Cadenza from "@cadenza.io/service";
|
|
71
|
+
|
|
72
|
+
const browserRuntime = Cadenza.createBrowserRuntimeActor({
|
|
73
|
+
actorName: "BrowserDashboardRuntimeActor",
|
|
74
|
+
service: {
|
|
75
|
+
name: "BrowserApp",
|
|
76
|
+
description: "Frontend app",
|
|
77
|
+
bootstrap: {
|
|
78
|
+
url: "https://cadenza-db.example.com:5000",
|
|
79
|
+
},
|
|
80
|
+
hydration,
|
|
81
|
+
useSocket: true,
|
|
82
|
+
},
|
|
83
|
+
initialProjectionState: {
|
|
84
|
+
liveFeed: [],
|
|
85
|
+
},
|
|
86
|
+
signalBindings: [
|
|
87
|
+
{
|
|
88
|
+
signal: "global.orders.updated",
|
|
89
|
+
reduce: (current, payload) => ({
|
|
90
|
+
...current,
|
|
91
|
+
liveFeed: [payload, ...current.liveFeed],
|
|
92
|
+
}),
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const unsubscribe = browserRuntime.subscribe((state) => {
|
|
98
|
+
console.log(state.ready, state.projectionState.liveFeed);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await browserRuntime.waitUntilReady();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Use `createCadenzaService(..., { isFrontend: true })` directly when you only need the lower-level frontend transport/bootstrap behavior. Use `createBrowserRuntimeActor(...)` when the frontend also needs actor-owned readiness and projected browser runtime state.
|
|
105
|
+
|
|
106
|
+
### Creating a Nuxt runtime wrapper
|
|
107
|
+
If your frontend is Nuxt, use `@cadenza.io/service/nuxt` on top of the shared browser actor. The Nuxt layer keeps the core runtime framework agnostic while hiding `useState`, plugin injection, and subscription wiring.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import Cadenza from "@cadenza.io/service";
|
|
111
|
+
import { defineCadenzaNuxtRuntimePlugin } from "@cadenza.io/service/nuxt";
|
|
112
|
+
|
|
113
|
+
export default defineCadenzaNuxtRuntimePlugin({
|
|
114
|
+
cadenza: Cadenza,
|
|
115
|
+
actorName: "BrowserDashboardRuntimeActor",
|
|
116
|
+
service: {
|
|
117
|
+
name: "BrowserApp",
|
|
118
|
+
description: "Nuxt dashboard runtime",
|
|
119
|
+
useSocket: true,
|
|
120
|
+
},
|
|
121
|
+
bootstrapUrl: (config) => config.public.cadenzaBootstrapUrl,
|
|
122
|
+
initialProjectionState: {
|
|
123
|
+
flags: {
|
|
124
|
+
maintenanceMode: false,
|
|
125
|
+
},
|
|
126
|
+
metrics: {
|
|
127
|
+
alertCount: 0,
|
|
128
|
+
},
|
|
129
|
+
liveFeed: [],
|
|
130
|
+
},
|
|
131
|
+
signalBindings: [
|
|
132
|
+
{
|
|
133
|
+
signal: "global.orders.updated",
|
|
134
|
+
reduce: (current, payload) => ({
|
|
135
|
+
...current,
|
|
136
|
+
metrics: {
|
|
137
|
+
...current.metrics,
|
|
138
|
+
alertCount: current.metrics.alertCount + 1,
|
|
139
|
+
},
|
|
140
|
+
liveFeed: [payload, ...current.liveFeed],
|
|
141
|
+
}),
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
commands: ({ cadenza, runtime }) => ({
|
|
145
|
+
refreshDashboard: async () => {
|
|
146
|
+
await runtime.waitUntilReady();
|
|
147
|
+
return cadenza.inquire("dashboard-refresh", {});
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The Nuxt entrypoint exposes:
|
|
154
|
+
|
|
155
|
+
- `defineCadenzaNuxtRuntimePlugin(...)`
|
|
156
|
+
- `useCadenzaRuntime()`
|
|
157
|
+
- `useCadenzaProjectionState()`
|
|
158
|
+
- `useCadenzaRuntimeReady()`
|
|
159
|
+
|
|
160
|
+
The intended model is projection-state-first: signals reduce into structured app state, and components read only the slices they care about.
|
|
161
|
+
|
|
162
|
+
### Creating a Vue runtime wrapper
|
|
163
|
+
If your frontend is plain Vue 3, use `@cadenza.io/service/vue`. The Vue layer keeps the shared browser actor as the authority and exposes a plugin-installable runtime with provide/inject and Vue-native reactivity.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { createApp } from "vue";
|
|
167
|
+
import Cadenza from "@cadenza.io/service";
|
|
168
|
+
import {
|
|
169
|
+
createCadenzaVueRuntime,
|
|
170
|
+
useCadenzaProjectionSelector,
|
|
171
|
+
useCadenzaRuntime,
|
|
172
|
+
useCadenzaRuntimeReady,
|
|
173
|
+
} from "@cadenza.io/service/vue";
|
|
174
|
+
|
|
175
|
+
const runtime = createCadenzaVueRuntime({
|
|
176
|
+
cadenza: Cadenza,
|
|
177
|
+
actorName: "BrowserDashboardRuntimeActor",
|
|
178
|
+
service: {
|
|
179
|
+
name: "BrowserApp",
|
|
180
|
+
description: "Vue dashboard runtime",
|
|
181
|
+
useSocket: true,
|
|
182
|
+
},
|
|
183
|
+
bootstrapUrl: () => window.__CADENZA_BOOTSTRAP_URL__,
|
|
184
|
+
initialProjectionState: {
|
|
185
|
+
metrics: {
|
|
186
|
+
alertCount: 0,
|
|
187
|
+
},
|
|
188
|
+
liveFeed: [],
|
|
189
|
+
},
|
|
190
|
+
signalBindings: [
|
|
191
|
+
{
|
|
192
|
+
signal: "global.orders.updated",
|
|
193
|
+
reduce: (current, payload) => ({
|
|
194
|
+
...current,
|
|
195
|
+
metrics: {
|
|
196
|
+
...current.metrics,
|
|
197
|
+
alertCount: current.metrics.alertCount + 1,
|
|
198
|
+
},
|
|
199
|
+
liveFeed: [payload, ...current.liveFeed],
|
|
200
|
+
}),
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
commands: ({ cadenza, runtime }) => ({
|
|
204
|
+
refreshDashboard: async () => {
|
|
205
|
+
await runtime.waitUntilReady();
|
|
206
|
+
return cadenza.inquire("dashboard-refresh", {});
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
function useDashboardRuntime() {
|
|
212
|
+
const alertCount = useCadenzaProjectionSelector(
|
|
213
|
+
(state) => state.metrics.alertCount,
|
|
214
|
+
);
|
|
215
|
+
const ready = useCadenzaRuntimeReady();
|
|
216
|
+
const runtime = useCadenzaRuntime();
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
alertCount,
|
|
220
|
+
ready,
|
|
221
|
+
refresh: () => runtime.commands.refreshDashboard(),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const app = createApp(App);
|
|
226
|
+
app.use(runtime);
|
|
227
|
+
app.mount("#app");
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
The Vue entrypoint exposes:
|
|
231
|
+
|
|
232
|
+
- `createCadenzaVueRuntime(...)`
|
|
233
|
+
- `useCadenzaRuntime()`
|
|
234
|
+
- `useCadenzaRuntimeState()`
|
|
235
|
+
- `useCadenzaProjectionState()`
|
|
236
|
+
- `useCadenzaProjectionSelector()`
|
|
237
|
+
- `useCadenzaRuntimeReady()`
|
|
238
|
+
|
|
239
|
+
Vue is the plain Vue 3 client-app layer. Nuxt remains the Nuxt-specific wrapper, and all wrappers sit on the same browser runtime actor authority.
|
|
240
|
+
|
|
241
|
+
### Creating a React runtime wrapper
|
|
242
|
+
If your frontend is React, use `@cadenza.io/service/react`. The React layer keeps the runtime object stable in context and lets components subscribe to projection slices with `useSyncExternalStore`.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { createElement } from "react";
|
|
246
|
+
import Cadenza from "@cadenza.io/service";
|
|
247
|
+
import {
|
|
248
|
+
CadenzaRuntimeProvider,
|
|
249
|
+
createCadenzaReactRuntime,
|
|
250
|
+
useCadenzaProjectionSelector,
|
|
251
|
+
useCadenzaRuntime,
|
|
252
|
+
} from "@cadenza.io/service/react";
|
|
253
|
+
|
|
254
|
+
const runtime = createCadenzaReactRuntime({
|
|
255
|
+
cadenza: Cadenza,
|
|
256
|
+
actorName: "BrowserDashboardRuntimeActor",
|
|
257
|
+
service: {
|
|
258
|
+
name: "BrowserApp",
|
|
259
|
+
description: "React dashboard runtime",
|
|
260
|
+
useSocket: true,
|
|
261
|
+
},
|
|
262
|
+
bootstrapUrl: () => window.__CADENZA_BOOTSTRAP_URL__,
|
|
263
|
+
initialProjectionState: {
|
|
264
|
+
metrics: {
|
|
265
|
+
alertCount: 0,
|
|
266
|
+
},
|
|
267
|
+
liveFeed: [],
|
|
268
|
+
},
|
|
269
|
+
signalBindings: [
|
|
270
|
+
{
|
|
271
|
+
signal: "global.orders.updated",
|
|
272
|
+
reduce: (current, payload) => ({
|
|
273
|
+
...current,
|
|
274
|
+
metrics: {
|
|
275
|
+
...current.metrics,
|
|
276
|
+
alertCount: current.metrics.alertCount + 1,
|
|
277
|
+
},
|
|
278
|
+
liveFeed: [payload, ...current.liveFeed],
|
|
279
|
+
}),
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
commands: ({ cadenza, runtime }) => ({
|
|
283
|
+
refreshDashboard: async () => {
|
|
284
|
+
await runtime.waitUntilReady();
|
|
285
|
+
return cadenza.inquire("dashboard-refresh", {});
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
function AlertCountBadge() {
|
|
291
|
+
const alertCount = useCadenzaProjectionSelector(
|
|
292
|
+
(state) => state.metrics.alertCount,
|
|
293
|
+
);
|
|
294
|
+
const runtime = useCadenzaRuntime();
|
|
295
|
+
return createElement(
|
|
296
|
+
"button",
|
|
297
|
+
{
|
|
298
|
+
onClick: () => void runtime.commands.refreshDashboard(),
|
|
299
|
+
},
|
|
300
|
+
`Alerts: ${alertCount}`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function App() {
|
|
305
|
+
return createElement(
|
|
306
|
+
CadenzaRuntimeProvider,
|
|
307
|
+
{ runtime },
|
|
308
|
+
createElement(AlertCountBadge),
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The React entrypoint exposes:
|
|
314
|
+
|
|
315
|
+
- `createCadenzaReactRuntime(...)`
|
|
316
|
+
- `CadenzaRuntimeProvider`
|
|
317
|
+
- `useCadenzaRuntime()`
|
|
318
|
+
- `useCadenzaProjectionState()`
|
|
319
|
+
- `useCadenzaProjectionSelector()`
|
|
320
|
+
- `useCadenzaRuntimeReady()`
|
|
321
|
+
|
|
322
|
+
Prefer `useCadenzaProjectionSelector()` for component-specific slices. Use `useCadenzaProjectionState()` only when a component truly needs the whole `{ ready, projectionState }` snapshot. For SSR-capable React environments such as Next, create the runtime in a client boundary and pass hydration explicitly when needed.
|
|
323
|
+
|
|
66
324
|
### SSR inquiries
|
|
67
325
|
For SSR use cases, use the request-scoped bridge for one-off distributed inquiries and pass dehydrated results to the browser runtime.
|
|
68
326
|
|