@almadar/shell-runtime 0.0.0-stage → 0.1.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 (180) hide show
  1. package/dist/chunk-2JU7Y4KU.js +21 -0
  2. package/dist/chunk-46RWK2B5.js +28 -0
  3. package/dist/chunk-4J2QEIUV.js +78 -0
  4. package/dist/chunk-4SEK5ER2.js +8 -0
  5. package/dist/chunk-4ZICQ5PM.js +192 -0
  6. package/dist/chunk-53IPZXDP.js +76 -0
  7. package/dist/chunk-5D63EMO5.js +16 -0
  8. package/dist/chunk-64IH2SMY.js +22 -0
  9. package/dist/chunk-7SDV3QWR.js +67 -0
  10. package/dist/chunk-CPSQXEJ6.js +55 -0
  11. package/dist/chunk-CQP5XAX6.js +173 -0
  12. package/dist/chunk-CROS2GEX.js +49 -0
  13. package/dist/chunk-D4XJTBLB.js +217 -0
  14. package/dist/chunk-D5USD2EX.js +232 -0
  15. package/dist/chunk-DYOJGLIX.js +25 -0
  16. package/dist/chunk-ELBLT2HZ.js +1 -0
  17. package/dist/chunk-EV56K4GB.js +63 -0
  18. package/dist/chunk-EZZYLTWY.js +1 -0
  19. package/dist/chunk-FQ6IZMIU.js +10 -0
  20. package/dist/chunk-FWA5K7Q2.js +48 -0
  21. package/dist/chunk-HC6ERSAH.js +55 -0
  22. package/dist/chunk-HLOUDLPI.js +48 -0
  23. package/dist/chunk-HMK6YMQS.js +135 -0
  24. package/dist/chunk-HNOAZWFH.js +19 -0
  25. package/dist/chunk-IHQLE5M7.js +62 -0
  26. package/dist/chunk-IOPUS6Q5.js +15 -0
  27. package/dist/chunk-JFWFDUTR.js +35 -0
  28. package/dist/chunk-LZIOTBFX.js +1 -0
  29. package/dist/chunk-MHYSHSRG.js +54 -0
  30. package/dist/chunk-MLKGABMK.js +7 -0
  31. package/dist/chunk-MZKIL5IN.js +74 -0
  32. package/dist/chunk-NAECVIAR.js +322 -0
  33. package/dist/chunk-NATGCIVM.js +583 -0
  34. package/dist/chunk-O57GKTYU.js +30 -0
  35. package/dist/chunk-ODJCZ27I.js +50 -0
  36. package/dist/chunk-P53CKOME.js +1 -0
  37. package/dist/chunk-Q2H75UYT.js +92 -0
  38. package/dist/chunk-Q7JK4KY7.js +9 -0
  39. package/dist/chunk-QELZ6TEJ.js +208 -0
  40. package/dist/chunk-QQRDUMB2.js +40 -0
  41. package/dist/chunk-RBUMDYFS.js +681 -0
  42. package/dist/chunk-REPX5QPI.js +57 -0
  43. package/dist/chunk-SAS5KKCR.js +43 -0
  44. package/dist/chunk-SKLMWHQD.js +109 -0
  45. package/dist/chunk-SOQDEPME.js +131 -0
  46. package/dist/chunk-SWPDU752.js +28 -0
  47. package/dist/chunk-T775TUCD.js +18 -0
  48. package/dist/chunk-UBN5JJKZ.js +26 -0
  49. package/dist/chunk-UJHOUZAL.js +36 -0
  50. package/dist/chunk-UP6GGGAN.js +34 -0
  51. package/dist/chunk-VMOBW7RK.js +21 -0
  52. package/dist/chunk-VNMG7NKY.js +69 -0
  53. package/dist/chunk-WNPNNYXY.js +22 -0
  54. package/dist/chunk-XB5GYODW.js +28 -0
  55. package/dist/chunk-XXWNMJI6.js +15 -0
  56. package/dist/chunk-YL2SO5TP.js +334 -0
  57. package/dist/chunk-YO4LWS3I.js +606 -0
  58. package/dist/chunk-ZAQSS47X.js +157 -0
  59. package/dist/chunk-ZCQUUJIF.js +129 -0
  60. package/dist/client/EventTransport.d.ts +131 -0
  61. package/dist/client/EventTransport.js +2 -0
  62. package/dist/client/ServerBridge.d.ts +126 -0
  63. package/dist/client/ServerBridge.js +3 -0
  64. package/dist/client/awaiting.d.ts +28 -0
  65. package/dist/client/awaiting.js +2 -0
  66. package/dist/client/channel-transport.d.ts +69 -0
  67. package/dist/client/channel-transport.js +2 -0
  68. package/dist/client/circuit-store.d.ts +76 -0
  69. package/dist/client/circuit-store.js +4 -0
  70. package/dist/client/client-kernel.d.ts +113 -0
  71. package/dist/client/client-kernel.js +1 -0
  72. package/dist/client/declared-input-dispatch.d.ts +5 -0
  73. package/dist/client/declared-input-dispatch.js +2 -0
  74. package/dist/client/inbound-dispatch.d.ts +5 -0
  75. package/dist/client/inbound-dispatch.js +2 -0
  76. package/dist/client/local-fold.d.ts +26 -0
  77. package/dist/client/local-fold.js +2 -0
  78. package/dist/client/render-sigils.d.ts +24 -0
  79. package/dist/client/render-sigils.js +2 -0
  80. package/dist/client/state-book.d.ts +37 -0
  81. package/dist/client/state-book.js +2 -0
  82. package/dist/client/trait-mount-error.d.ts +9 -0
  83. package/dist/client/trait-mount-error.js +2 -0
  84. package/dist/client/trait-types.d.ts +67 -0
  85. package/dist/client/trait-types.js +1 -0
  86. package/dist/credentials/env-vars.d.ts +14 -0
  87. package/dist/credentials/env-vars.js +3 -0
  88. package/dist/credentials/scope.d.ts +50 -0
  89. package/dist/credentials/scope.js +2 -0
  90. package/dist/credentials/seed.d.ts +21 -0
  91. package/dist/credentials/seed.js +2 -0
  92. package/dist/credentials/store.d.ts +110 -0
  93. package/dist/credentials/store.js +2 -0
  94. package/dist/effects/in-flight-calls.d.ts +36 -0
  95. package/dist/effects/in-flight-calls.js +2 -0
  96. package/dist/effects/on-device-model.d.ts +22 -0
  97. package/dist/effects/on-device-model.js +2 -0
  98. package/dist/events/EventBus.d.ts +90 -0
  99. package/dist/events/EventBus.js +2 -0
  100. package/dist/events/emit-stamp.d.ts +47 -0
  101. package/dist/events/emit-stamp.js +2 -0
  102. package/dist/index-hT1xCdTq.d.ts +46 -0
  103. package/dist/index.d.ts +60 -0
  104. package/dist/index.js +59 -0
  105. package/dist/kernel/beacon.d.ts +32 -0
  106. package/dist/kernel/beacon.js +2 -0
  107. package/dist/kernel/decode.d.ts +15 -0
  108. package/dist/kernel/decode.js +2 -0
  109. package/dist/kernel/engine.d.ts +94 -0
  110. package/dist/kernel/engine.js +11 -0
  111. package/dist/kernel/frame-applier.d.ts +43 -0
  112. package/dist/kernel/frame-applier.js +2 -0
  113. package/dist/kernel/host.d.ts +95 -0
  114. package/dist/kernel/host.js +9 -0
  115. package/dist/kernel/http.d.ts +302 -0
  116. package/dist/kernel/http.js +6 -0
  117. package/dist/kernel/lane.d.ts +28 -0
  118. package/dist/kernel/lane.js +2 -0
  119. package/dist/kernel/oauth-effects.d.ts +25 -0
  120. package/dist/kernel/oauth-effects.js +7 -0
  121. package/dist/kernel/oauth-port.d.ts +31 -0
  122. package/dist/kernel/oauth-port.js +2 -0
  123. package/dist/kernel/os-port.d.ts +133 -0
  124. package/dist/kernel/os-port.js +2 -0
  125. package/dist/kernel/program-effects.d.ts +65 -0
  126. package/dist/kernel/program-effects.js +2 -0
  127. package/dist/kernel/wire.d.ts +66 -0
  128. package/dist/kernel/wire.js +1 -0
  129. package/dist/loader/http-loader.d.ts +111 -0
  130. package/dist/loader/http-loader.js +2 -0
  131. package/dist/loader/lazy-page.d.ts +12 -0
  132. package/dist/loader/lazy-page.js +2 -0
  133. package/dist/loader/schema-loader.d.ts +160 -0
  134. package/dist/loader/schema-loader.js +1 -0
  135. package/dist/persistence/native-memory.d.ts +28 -0
  136. package/dist/persistence/native-memory.js +2 -0
  137. package/dist/runtime/effects/composition/compose-behaviors.d.ts +58 -0
  138. package/dist/runtime/effects/composition/compose-behaviors.js +4 -0
  139. package/dist/runtime/effects/composition/event-wiring.d.ts +38 -0
  140. package/dist/runtime/effects/composition/event-wiring.js +2 -0
  141. package/dist/runtime/effects/composition/index.d.ts +5 -0
  142. package/dist/runtime/effects/composition/index.js +6 -0
  143. package/dist/runtime/effects/composition/layout-strategy.d.ts +35 -0
  144. package/dist/runtime/effects/composition/layout-strategy.js +2 -0
  145. package/dist/runtime/effects/composition/pipe.d.ts +25 -0
  146. package/dist/runtime/effects/composition/pipe.js +2 -0
  147. package/dist/runtime/entities/mockStoreSeed.d.ts +56 -0
  148. package/dist/runtime/entities/mockStoreSeed.js +3 -0
  149. package/dist/runtime/entities/seedBrowserStore.d.ts +28 -0
  150. package/dist/runtime/entities/seedBrowserStore.js +2 -0
  151. package/dist/runtime/entities/std-mock-seed.d.ts +87 -0
  152. package/dist/runtime/entities/std-mock-seed.js +2 -0
  153. package/dist/runtime/evaluation/local-store-transport.d.ts +68 -0
  154. package/dist/runtime/evaluation/local-store-transport.js +18 -0
  155. package/dist/runtime/evaluation/residence-transport.d.ts +15 -0
  156. package/dist/runtime/evaluation/residence-transport.js +2 -0
  157. package/dist/runtime/evaluation/routed-persistence.d.ts +9 -0
  158. package/dist/runtime/evaluation/routed-persistence.js +2 -0
  159. package/dist/runtime/events/identity/routing.d.ts +84 -0
  160. package/dist/runtime/events/identity/routing.js +2 -0
  161. package/dist/runtime/time/TickScheduler.d.ts +77 -0
  162. package/dist/runtime/time/TickScheduler.js +3 -0
  163. package/dist/runtime/time/cron.d.ts +25 -0
  164. package/dist/runtime/time/cron.js +2 -0
  165. package/dist/runtime/time/duration.d.ts +20 -0
  166. package/dist/runtime/time/duration.js +2 -0
  167. package/dist/runtime/traits/OrbitalTraitParsing.d.ts +34 -0
  168. package/dist/runtime/traits/OrbitalTraitParsing.js +2 -0
  169. package/dist/runtime/traits/listen-targets.d.ts +16 -0
  170. package/dist/runtime/traits/listen-targets.js +3 -0
  171. package/dist/runtime/traits/trait-index.d.ts +35 -0
  172. package/dist/runtime/traits/trait-index.js +3 -0
  173. package/dist/runtime/types.d.ts +574 -0
  174. package/dist/runtime/types.js +2 -0
  175. package/dist/service/default-call-service.d.ts +23 -0
  176. package/dist/service/default-call-service.js +3 -0
  177. package/dist/service/service-provider.d.ts +37 -0
  178. package/dist/service/service-provider.js +2 -0
  179. package/package.json +46 -3
  180. package/README.md +0 -3
@@ -0,0 +1,92 @@
1
+ import { normalizeEventKey, LIFECYCLE_EVENTS } from '@almadar/core';
2
+
3
+ // src/client/state-book.ts
4
+ function findInitialState(trait) {
5
+ const markedInitial = trait.states?.find((s) => s.isInitial)?.name;
6
+ return markedInitial ?? trait.states?.[0]?.name ?? "unknown";
7
+ }
8
+ function createInitialTraitState(trait) {
9
+ return {
10
+ traitName: trait.name,
11
+ currentState: findInitialState(trait),
12
+ previousState: null,
13
+ lastEvent: null,
14
+ context: {}
15
+ };
16
+ }
17
+ function findMatchingTransitions(trait, currentState, eventKey, eventId) {
18
+ return (trait.transitions ?? []).filter((t) => {
19
+ const fromMatches = Array.isArray(t.from) ? t.from.includes(currentState) : t.from === currentState;
20
+ if (!fromMatches) return false;
21
+ if (eventId && t.eventId) return t.eventId === eventId;
22
+ return t.event === eventKey;
23
+ });
24
+ }
25
+ function findTransition(trait, currentState, eventKey, eventId) {
26
+ return findMatchingTransitions(trait, currentState, eventKey, eventId)[0];
27
+ }
28
+ var SINGLETON_SCOPE = "__singleton__";
29
+ var key = (traitName, entityId) => `${traitName}::${entityId ?? SINGLETON_SCOPE}`;
30
+ var StateBook = class {
31
+ constructor(traits = [], observer) {
32
+ this.observer = observer;
33
+ for (const trait of traits) this.traits.set(trait.name, trait);
34
+ }
35
+ observer;
36
+ traits = /* @__PURE__ */ new Map();
37
+ states = /* @__PURE__ */ new Map();
38
+ /** The trait's state, its initial state until the kernel reports one; `undefined` for a trait not on the page. */
39
+ getState(traitName, entityId) {
40
+ const recorded = this.states.get(key(traitName, entityId));
41
+ if (recorded !== void 0) return recorded;
42
+ const trait = this.traits.get(traitName);
43
+ return trait === void 0 ? void 0 : createInitialTraitState(trait);
44
+ }
45
+ /** Each trait's singleton-scope state. */
46
+ getAllStates() {
47
+ const out = /* @__PURE__ */ new Map();
48
+ for (const name of this.traits.keys()) {
49
+ const state = this.getState(name);
50
+ if (state !== void 0) out.set(name, state);
51
+ }
52
+ return out;
53
+ }
54
+ /** Whether the trait has an arm on the event from its current state. */
55
+ canHandleEvent(traitName, eventKey, entityId, eventId) {
56
+ const trait = this.traits.get(traitName);
57
+ const state = this.getState(traitName, entityId);
58
+ if (trait === void 0 || state === void 0) return false;
59
+ return findTransition(trait, state.currentState, normalizeEventKey(eventKey), eventId) !== void 0;
60
+ }
61
+ /**
62
+ * The lifecycle event an embedded child can be repainted with: the one it handles from its current state,
63
+ * provided every matching arm stays in that state and only renders.
64
+ */
65
+ repaintLifecycleEvent(traitName, entityId) {
66
+ const trait = this.traits.get(traitName);
67
+ const state = this.getState(traitName, entityId);
68
+ if (trait === void 0 || state === void 0) return void 0;
69
+ for (const event of LIFECYCLE_EVENTS) {
70
+ const arms = findMatchingTransitions(trait, state.currentState, event);
71
+ if (arms.length === 0) continue;
72
+ const repaints = arms.every((t) => t.to === state.currentState && (t.effects ?? []).every((effect) => Array.isArray(effect) && effect[0] === "render-ui"));
73
+ return repaints ? event : void 0;
74
+ }
75
+ return void 0;
76
+ }
77
+ /** Record the state the kernel reports. No-op for a trait not on the page. */
78
+ seedState(traitName, currentState, entityId) {
79
+ const trait = this.traits.get(traitName);
80
+ if (trait === void 0) return;
81
+ const existing = this.states.get(key(traitName, entityId)) ?? createInitialTraitState(trait);
82
+ this.states.set(key(traitName, entityId), { ...existing, currentState, previousState: existing.currentState });
83
+ }
84
+ /** Undo an optimistic commit, reporting the hop back to the observer. */
85
+ rollbackState(traitName, toState, entityId, cause) {
86
+ const from = this.getState(traitName, entityId)?.currentState;
87
+ this.seedState(traitName, toState, entityId);
88
+ if (from !== void 0 && from !== toState) this.observer?.onRollback?.({ traitName, from, to: toState, cause });
89
+ }
90
+ };
91
+
92
+ export { StateBook, createInitialTraitState, findInitialState, findMatchingTransitions, findTransition };
@@ -0,0 +1,9 @@
1
+ import { CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV } from './chunk-NAECVIAR.js';
2
+
3
+ // src/credentials/env-vars.ts
4
+ var STORE_BOOTSTRAP_ENV_VARS = /* @__PURE__ */ new Set([CREDENTIAL_MASTER_KEY_ENV, CREDENTIAL_PREVIOUS_MASTER_KEY_ENV]);
5
+ function allCredentialEnvVars() {
6
+ return new Set(STORE_BOOTSTRAP_ENV_VARS);
7
+ }
8
+
9
+ export { STORE_BOOTSTRAP_ENV_VARS, allCredentialEnvVars };
@@ -0,0 +1,208 @@
1
+ import { createLogger } from '@almadar/logger';
2
+ import { RowQueryPageSchema, OrbitalRegisterResponseSchema } from '@almadar/core';
3
+
4
+ // src/client/EventTransport.ts
5
+ var log = createLogger("almadar:runtime:event-transport");
6
+ function deriveCarriesCircuitState(topology) {
7
+ return topology !== "stateful";
8
+ }
9
+ async function authHeaders(getAccessToken) {
10
+ const headers = { "Content-Type": "application/json" };
11
+ const token = getAccessToken ? await getAccessToken() : void 0;
12
+ if (token) headers.Authorization = `Bearer ${token}`;
13
+ return headers;
14
+ }
15
+ function deriveEventsUrl(serverUrl) {
16
+ const trimmed = serverUrl.replace(/\/+$/, "");
17
+ const apiRoot = trimmed.replace(/\/[^/]*$/, "");
18
+ return `${apiRoot}/events`;
19
+ }
20
+ function isBusPushEnvelope(value) {
21
+ return value.type === "bus" && typeof value.event === "string";
22
+ }
23
+ function isDispatchPushEnvelope(value) {
24
+ return value.type === "dispatch" && typeof value.orbitalName === "string" && value.request !== void 0 && value.response !== void 0;
25
+ }
26
+ var EVENT_SOURCE_CLOSED = 2;
27
+ var REOPEN_DELAY_MS = 1e3;
28
+ var pushChannels = /* @__PURE__ */ new Map();
29
+ function parseFrameNumber(id) {
30
+ const dash = id.lastIndexOf("-");
31
+ if (dash <= 0) return void 0;
32
+ const n = Number(id.slice(dash + 1));
33
+ return Number.isInteger(n) ? { boot: id.slice(0, dash), n } : void 0;
34
+ }
35
+ var lastFrameByClient = /* @__PURE__ */ new Map();
36
+ function acquirePushChannel(key, resolveUrl, resumeKey, subscriber) {
37
+ let channel = pushChannels.get(key);
38
+ if (channel === void 0) {
39
+ const created = { source: void 0, subscribers: /* @__PURE__ */ new Set(), closed: false };
40
+ const open = async () => {
41
+ let url;
42
+ try {
43
+ url = await resolveUrl();
44
+ } catch (err) {
45
+ log.error("push:open-failed", { error: err instanceof Error ? err.message : String(err) });
46
+ return;
47
+ }
48
+ if (created.closed) return;
49
+ const source = new EventSource(url);
50
+ created.source = source;
51
+ source.onmessage = (ev) => {
52
+ let parsed;
53
+ try {
54
+ parsed = JSON.parse(ev.data);
55
+ } catch (err) {
56
+ log.warn("push:parse-failed", { error: err instanceof Error ? err.message : String(err) });
57
+ return;
58
+ }
59
+ const number = ev.lastEventId ? parseFrameNumber(ev.lastEventId) : void 0;
60
+ if (number !== void 0 && resumeKey !== void 0) {
61
+ const seen = lastFrameByClient.get(resumeKey);
62
+ if (seen !== void 0 && seen.boot === number.boot && number.n <= seen.n) return;
63
+ lastFrameByClient.set(resumeKey, number);
64
+ }
65
+ for (const sub of created.subscribers) sub(parsed);
66
+ };
67
+ source.onerror = () => {
68
+ log.warn("push:connection-error", { channel: key });
69
+ if (source.readyState === EVENT_SOURCE_CLOSED && !created.closed) {
70
+ created.source = void 0;
71
+ setTimeout(() => {
72
+ if (!created.closed) void open();
73
+ }, REOPEN_DELAY_MS);
74
+ }
75
+ };
76
+ };
77
+ pushChannels.set(key, created);
78
+ void open();
79
+ channel = created;
80
+ }
81
+ channel.subscribers.add(subscriber);
82
+ return () => {
83
+ channel.subscribers.delete(subscriber);
84
+ if (channel.subscribers.size === 0) {
85
+ channel.closed = true;
86
+ channel.source?.close();
87
+ pushChannels.delete(key);
88
+ }
89
+ };
90
+ }
91
+ var COMPRESSED_BODY_MIN_BYTES = 32 * 1024;
92
+ async function encodeJsonBody(value, compress) {
93
+ const text = JSON.stringify(value);
94
+ if (!compress || text.length < COMPRESSED_BODY_MIN_BYTES || typeof CompressionStream === "undefined") return { body: text };
95
+ const bytes = new TextEncoder().encode(text);
96
+ const source = new ReadableStream({ start(controller) {
97
+ controller.enqueue(bytes);
98
+ controller.close();
99
+ } });
100
+ const gzipped = source.pipeThrough(new CompressionStream("gzip"));
101
+ return { body: new Uint8Array(await new Response(gzipped).arrayBuffer()), encoding: "gzip" };
102
+ }
103
+ async function jsonPost(fetchFn, url, value, getAccessToken, compress) {
104
+ const headers = await authHeaders(getAccessToken);
105
+ const { body, encoding } = await encodeJsonBody(value, compress);
106
+ if (encoding) headers["Content-Encoding"] = encoding;
107
+ return fetchFn(url, { method: "POST", headers, body });
108
+ }
109
+ function createHttpTransport(options) {
110
+ const { serverUrl, getAccessToken } = options;
111
+ const fetchFn = options.fetch ?? fetch.bind(globalThis);
112
+ const compress = options.compressRequests === true;
113
+ let behavior;
114
+ const openPushChannel = (params, subscriber) => {
115
+ if (typeof EventSource === "undefined") return () => {
116
+ };
117
+ const eventsUrl = deriveEventsUrl(serverUrl);
118
+ const resumeKey = params["clientId"] !== void 0 ? `${eventsUrl}|${params["clientId"]}` : void 0;
119
+ const withResume = (search) => {
120
+ const seen = resumeKey !== void 0 ? lastFrameByClient.get(resumeKey) : void 0;
121
+ if (seen !== void 0) search.set("since", `${seen.boot}-${seen.n}`);
122
+ return `${eventsUrl}?${search.toString()}`;
123
+ };
124
+ const key = `${eventsUrl}?${new URLSearchParams(params).toString()}`;
125
+ const resolveUrl = async () => {
126
+ const reply = await fetchFn(`${eventsUrl}/ticket`, { method: "POST", headers: await authHeaders(getAccessToken) });
127
+ if (!reply.ok) throw new Error(`the server refused a stream ticket: ${reply.status}`);
128
+ const body = await reply.json();
129
+ if (typeof body.ticket !== "string" || body.ticket.length === 0) throw new Error("the server sent no stream ticket");
130
+ return withResume(new URLSearchParams({ ...params, ticket: body.ticket }));
131
+ };
132
+ return acquirePushChannel(key, resolveUrl, resumeKey, subscriber);
133
+ };
134
+ return {
135
+ async register(schema) {
136
+ behavior = schema.name;
137
+ try {
138
+ const res = await jsonPost(fetchFn, `${serverUrl}/register`, { schema }, getAccessToken, compress);
139
+ const parsed = OrbitalRegisterResponseSchema.safeParse(await res.json());
140
+ if (!parsed.success) {
141
+ log.error("register:malformed-response", { issues: JSON.stringify(parsed.error.issues) });
142
+ return { success: false, carriesCircuitState: deriveCarriesCircuitState(void 0) };
143
+ }
144
+ return {
145
+ success: parsed.data.success,
146
+ carriesCircuitState: deriveCarriesCircuitState(parsed.data.topology)
147
+ };
148
+ } catch (err) {
149
+ if (err instanceof TypeError) {
150
+ log.warn("register:failed", { error: err.message });
151
+ } else {
152
+ log.error("register:failed", { error: err instanceof Error ? err : String(err) });
153
+ }
154
+ return { success: false, carriesCircuitState: true };
155
+ }
156
+ },
157
+ async unregister() {
158
+ try {
159
+ await fetchFn(`${serverUrl}/unregister`, { method: "DELETE", headers: await authHeaders(getAccessToken) });
160
+ } catch (error) {
161
+ log.warn("unregister-failed", { error: error instanceof Error ? error.message : String(error) });
162
+ }
163
+ },
164
+ async send(orbitalName, request) {
165
+ const res = await jsonPost(
166
+ fetchFn,
167
+ `${serverUrl}/${orbitalName}/events`,
168
+ request.behavior === void 0 && behavior !== void 0 ? { ...request, behavior } : request,
169
+ getAccessToken,
170
+ compress
171
+ );
172
+ return await res.json();
173
+ },
174
+ async resolveRows(reference) {
175
+ const res = await jsonPost(fetchFn, `${serverUrl}/resolve-rows`, { ref: reference }, getAccessToken, compress);
176
+ if (!res.ok) throw new Error(`resolve-rows: the server answered ${res.status}`);
177
+ return RowQueryPageSchema.parse(await res.json());
178
+ },
179
+ subscribe(onPush, params = {}) {
180
+ return openPushChannel(params, (envelope) => {
181
+ if (isBusPushEnvelope(envelope)) onPush({ event: envelope.event, payload: envelope.payload, source: envelope.source }, envelope.target ?? "peers");
182
+ });
183
+ },
184
+ subscribeHostDispatches(onDispatch, params = {}) {
185
+ return openPushChannel(params, (envelope) => {
186
+ if (isDispatchPushEnvelope(envelope)) onDispatch(envelope.orbitalName, envelope.request, envelope.response);
187
+ });
188
+ }
189
+ };
190
+ }
191
+ function createInProcessTransport(evaluate, options = {}) {
192
+ return {
193
+ async register(schema) {
194
+ await options.onRegister?.(schema);
195
+ return { success: true, carriesCircuitState: options.carriesCircuitState ?? false };
196
+ },
197
+ async unregister() {
198
+ await options.onUnregister?.();
199
+ },
200
+ async send(orbitalName, request) {
201
+ return evaluate(orbitalName, request);
202
+ },
203
+ ...options.resolveRows !== void 0 ? { resolveRows: options.resolveRows } : {}
204
+ // No `subscribe` — an in-process transport has no server to push from.
205
+ };
206
+ }
207
+
208
+ export { COMPRESSED_BODY_MIN_BYTES, createHttpTransport, createInProcessTransport, deriveCarriesCircuitState, encodeJsonBody };
@@ -0,0 +1,40 @@
1
+ // src/client/local-fold.ts
2
+ function mirrorResponse(store, frameKeyOf, response) {
3
+ for (const [trait, state] of Object.entries(response.states)) {
4
+ if (store.states.getState(trait)?.currentState !== state) store.states.seedState(trait, state);
5
+ }
6
+ for (const [trait, row] of Object.entries(response.entityByTrait ?? {})) {
7
+ const frameKey = frameKeyOf(trait);
8
+ if (frameKey === void 0) continue;
9
+ store.frames.set(frameKey, { ...store.frames.get(frameKey) ?? {}, ...row });
10
+ }
11
+ for (const effect of response.clientEffectsByTrait ?? []) {
12
+ if (effect.callsitePayload !== void 0) store.callsitePayloads.set(effect.traitName, effect.callsitePayload);
13
+ }
14
+ }
15
+ function traceResponse(observer, response) {
16
+ if (observer === void 0) return;
17
+ for (const hop of response.transitions ?? []) {
18
+ observer.onTransition({
19
+ traitName: hop.trait,
20
+ from: hop.from,
21
+ to: hop.to,
22
+ event: hop.event,
23
+ ...hop.firedArm !== void 0 ? { firedArm: hop.firedArm } : {},
24
+ ...hop.guardResult !== void 0 ? { guardResult: hop.guardResult } : {},
25
+ effects: hop.effects,
26
+ ...hop.observed !== void 0 ? { observed: hop.observed } : {}
27
+ });
28
+ }
29
+ }
30
+ function createLocalFold(opts) {
31
+ return {
32
+ foldLocalResponse: async (response, traceHops, notify) => {
33
+ if (traceHops) traceResponse(opts.observer, response);
34
+ mirrorResponse(opts.store, opts.frameKeyOf, response);
35
+ if (notify) opts.store.notify();
36
+ }
37
+ };
38
+ }
39
+
40
+ export { createLocalFold, mirrorResponse, traceResponse };