@almadar/shell-runtime 0.1.0 → 1.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 (167) hide show
  1. package/dist/chunk-2WCVOMZ2.js +112 -0
  2. package/dist/chunk-57SBCUSM.js +62 -0
  3. package/dist/{chunk-Q2H75UYT.js → chunk-A2JJT4GA.js} +1 -37
  4. package/dist/chunk-BAS26HBN.js +10 -0
  5. package/dist/{chunk-REPX5QPI.js → chunk-BOVU4TCQ.js} +11 -3
  6. package/dist/chunk-BY5G4225.js +6 -0
  7. package/dist/chunk-DFDNHVDW.js +284 -0
  8. package/dist/{chunk-NATGCIVM.js → chunk-JVSREWQO.js} +378 -130
  9. package/dist/{chunk-DYOJGLIX.js → chunk-LKWYCYX5.js} +2 -5
  10. package/dist/chunk-LYFIQPXX.js +1 -0
  11. package/dist/{chunk-ODJCZ27I.js → chunk-N7HYNKK6.js} +35 -2
  12. package/dist/{chunk-4J2QEIUV.js → chunk-NTFQ36UN.js} +4 -30
  13. package/dist/chunk-NU6LVKGS.js +15 -0
  14. package/dist/{chunk-VNMG7NKY.js → chunk-OQVSN7DP.js} +21 -26
  15. package/dist/chunk-P2N6K2IV.js +20 -0
  16. package/dist/{chunk-QQRDUMB2.js → chunk-QCJWPXLH.js} +11 -11
  17. package/dist/{chunk-QELZ6TEJ.js → chunk-UD2CXYSJ.js} +39 -3
  18. package/dist/{chunk-UJHOUZAL.js → chunk-V4EMDPCO.js} +2 -5
  19. package/dist/chunk-VKQA2DJX.js +409 -0
  20. package/dist/chunk-VNGXRYFF.js +9 -0
  21. package/dist/{chunk-HNOAZWFH.js → chunk-WGCWJOT2.js} +2 -0
  22. package/dist/chunk-XZGVOBY6.js +33 -0
  23. package/dist/chunk-ZUSM4VW4.js +197 -0
  24. package/dist/client/EventTransport.d.ts +23 -7
  25. package/dist/client/EventTransport.js +1 -2
  26. package/dist/client/awaiting.js +0 -1
  27. package/dist/client/channel-transport.d.ts +6 -6
  28. package/dist/client/channel-transport.js +0 -1
  29. package/dist/client/circuit-store.d.ts +16 -5
  30. package/dist/client/circuit-store.js +2 -3
  31. package/dist/client/client-kernel.d.ts +36 -15
  32. package/dist/client/declared-input-dispatch.d.ts +19 -2
  33. package/dist/client/declared-input-dispatch.js +1 -2
  34. package/dist/client/inbound-dispatch.d.ts +21 -2
  35. package/dist/client/inbound-dispatch.js +1 -2
  36. package/dist/client/local-fold.d.ts +15 -8
  37. package/dist/client/local-fold.js +1 -2
  38. package/dist/client/render-sigils.js +0 -1
  39. package/dist/client/state-book.d.ts +9 -16
  40. package/dist/client/state-book.js +1 -2
  41. package/dist/client/trait-mount-error.js +0 -1
  42. package/dist/credentials/env-vars.d.ts +5 -1
  43. package/dist/credentials/env-vars.js +1 -3
  44. package/dist/credentials/scope.d.ts +8 -7
  45. package/dist/credentials/scope.js +0 -1
  46. package/dist/credentials/vault.d.ts +142 -0
  47. package/dist/credentials/vault.js +1 -0
  48. package/dist/effects/in-flight-calls.js +0 -1
  49. package/dist/effects/on-device-model.js +0 -1
  50. package/dist/events/EventBus.d.ts +1 -4
  51. package/dist/events/EventBus.js +0 -1
  52. package/dist/events/emit-stamp.js +0 -1
  53. package/dist/index.d.ts +25 -42
  54. package/dist/index.js +27 -45
  55. package/dist/kernel/decode.d.ts +10 -10
  56. package/dist/kernel/decode.js +1 -2
  57. package/dist/kernel/engine.d.ts +133 -31
  58. package/dist/kernel/engine.js +7 -9
  59. package/dist/kernel/frame-applier.d.ts +8 -7
  60. package/dist/kernel/frame-applier.js +1 -2
  61. package/dist/kernel/host.d.ts +148 -16
  62. package/dist/kernel/host.js +4 -7
  63. package/dist/kernel/lane.d.ts +1 -22
  64. package/dist/kernel/lane.js +1 -2
  65. package/dist/kernel/os-fetch-port.d.ts +7 -0
  66. package/dist/kernel/os-fetch-port.js +3 -0
  67. package/dist/kernel/os-port.d.ts +30 -8
  68. package/dist/kernel/os-port.js +1 -2
  69. package/dist/kernel/program-effects.d.ts +11 -28
  70. package/dist/kernel/program-effects.js +1 -2
  71. package/dist/kernel/secret-ports.d.ts +139 -0
  72. package/dist/kernel/secret-ports.js +2 -0
  73. package/dist/kernel/wire.d.ts +113 -12
  74. package/dist/loader/fetch-loader.d.ts +26 -0
  75. package/dist/loader/fetch-loader.js +1 -0
  76. package/dist/loader/lazy-page.js +0 -1
  77. package/dist/loader/schema-loader.d.ts +1 -17
  78. package/dist/persistence/native-memory.js +0 -1
  79. package/dist/runtime/entities/declaredCollections.d.ts +6 -0
  80. package/dist/runtime/entities/declaredCollections.js +1 -0
  81. package/dist/runtime/evaluation/local-store-transport.d.ts +16 -23
  82. package/dist/runtime/evaluation/local-store-transport.js +9 -13
  83. package/dist/runtime/evaluation/residence-transport.d.ts +3 -3
  84. package/dist/runtime/evaluation/residence-transport.js +1 -2
  85. package/dist/runtime/evaluation/routed-persistence.js +0 -1
  86. package/dist/runtime/events/identity/routing.d.ts +2 -53
  87. package/dist/runtime/events/identity/routing.js +1 -2
  88. package/dist/runtime/types.d.ts +5 -205
  89. package/dist/runtime/types.js +1 -2
  90. package/dist/service/default-call-service.js +0 -1
  91. package/dist/service/service-provider.js +0 -1
  92. package/package.json +8 -5
  93. package/dist/chunk-2JU7Y4KU.js +0 -21
  94. package/dist/chunk-46RWK2B5.js +0 -28
  95. package/dist/chunk-4ZICQ5PM.js +0 -192
  96. package/dist/chunk-53IPZXDP.js +0 -76
  97. package/dist/chunk-5D63EMO5.js +0 -16
  98. package/dist/chunk-CPSQXEJ6.js +0 -55
  99. package/dist/chunk-CQP5XAX6.js +0 -173
  100. package/dist/chunk-CROS2GEX.js +0 -49
  101. package/dist/chunk-D4XJTBLB.js +0 -217
  102. package/dist/chunk-D5USD2EX.js +0 -232
  103. package/dist/chunk-EV56K4GB.js +0 -63
  104. package/dist/chunk-FQ6IZMIU.js +0 -10
  105. package/dist/chunk-HMK6YMQS.js +0 -135
  106. package/dist/chunk-IHQLE5M7.js +0 -62
  107. package/dist/chunk-JFWFDUTR.js +0 -35
  108. package/dist/chunk-MHYSHSRG.js +0 -54
  109. package/dist/chunk-MLKGABMK.js +0 -7
  110. package/dist/chunk-NAECVIAR.js +0 -322
  111. package/dist/chunk-Q7JK4KY7.js +0 -9
  112. package/dist/chunk-RBUMDYFS.js +0 -681
  113. package/dist/chunk-SAS5KKCR.js +0 -43
  114. package/dist/chunk-SWPDU752.js +0 -28
  115. package/dist/chunk-T775TUCD.js +0 -18
  116. package/dist/chunk-VMOBW7RK.js +0 -21
  117. package/dist/chunk-WNPNNYXY.js +0 -22
  118. package/dist/chunk-XB5GYODW.js +0 -28
  119. package/dist/chunk-YL2SO5TP.js +0 -334
  120. package/dist/chunk-YO4LWS3I.js +0 -606
  121. package/dist/chunk-ZAQSS47X.js +0 -157
  122. package/dist/chunk-ZCQUUJIF.js +0 -129
  123. package/dist/client/ServerBridge.d.ts +0 -126
  124. package/dist/client/ServerBridge.js +0 -3
  125. package/dist/credentials/seed.d.ts +0 -21
  126. package/dist/credentials/seed.js +0 -2
  127. package/dist/credentials/store.d.ts +0 -110
  128. package/dist/credentials/store.js +0 -2
  129. package/dist/index-hT1xCdTq.d.ts +0 -46
  130. package/dist/kernel/beacon.d.ts +0 -32
  131. package/dist/kernel/beacon.js +0 -2
  132. package/dist/kernel/http.d.ts +0 -302
  133. package/dist/kernel/http.js +0 -6
  134. package/dist/kernel/oauth-effects.d.ts +0 -25
  135. package/dist/kernel/oauth-effects.js +0 -7
  136. package/dist/kernel/oauth-port.d.ts +0 -31
  137. package/dist/kernel/oauth-port.js +0 -2
  138. package/dist/loader/http-loader.d.ts +0 -111
  139. package/dist/loader/http-loader.js +0 -2
  140. package/dist/runtime/effects/composition/compose-behaviors.d.ts +0 -58
  141. package/dist/runtime/effects/composition/compose-behaviors.js +0 -4
  142. package/dist/runtime/effects/composition/event-wiring.d.ts +0 -38
  143. package/dist/runtime/effects/composition/event-wiring.js +0 -2
  144. package/dist/runtime/effects/composition/index.d.ts +0 -5
  145. package/dist/runtime/effects/composition/index.js +0 -6
  146. package/dist/runtime/effects/composition/layout-strategy.d.ts +0 -35
  147. package/dist/runtime/effects/composition/layout-strategy.js +0 -2
  148. package/dist/runtime/effects/composition/pipe.d.ts +0 -25
  149. package/dist/runtime/effects/composition/pipe.js +0 -2
  150. package/dist/runtime/entities/mockStoreSeed.d.ts +0 -56
  151. package/dist/runtime/entities/mockStoreSeed.js +0 -3
  152. package/dist/runtime/entities/seedBrowserStore.d.ts +0 -28
  153. package/dist/runtime/entities/seedBrowserStore.js +0 -2
  154. package/dist/runtime/entities/std-mock-seed.d.ts +0 -87
  155. package/dist/runtime/entities/std-mock-seed.js +0 -2
  156. package/dist/runtime/time/TickScheduler.d.ts +0 -77
  157. package/dist/runtime/time/TickScheduler.js +0 -3
  158. package/dist/runtime/time/cron.d.ts +0 -25
  159. package/dist/runtime/time/cron.js +0 -2
  160. package/dist/runtime/time/duration.d.ts +0 -20
  161. package/dist/runtime/time/duration.js +0 -2
  162. package/dist/runtime/traits/OrbitalTraitParsing.d.ts +0 -34
  163. package/dist/runtime/traits/OrbitalTraitParsing.js +0 -2
  164. package/dist/runtime/traits/listen-targets.d.ts +0 -16
  165. package/dist/runtime/traits/listen-targets.js +0 -3
  166. package/dist/runtime/traits/trait-index.d.ts +0 -35
  167. package/dist/runtime/traits/trait-index.js +0 -3
@@ -1,192 +0,0 @@
1
- import { isJsonObject } from '@almadar/core';
2
-
3
- // src/kernel/oauth-port.ts
4
- var PENDING_GRACE_MS = 60 * 60 * 1e3;
5
- var NO_CALLER = "a provider connection needs a signed-in caller";
6
- var NO_CONNECTIONS = "no OAuth connection store is installed on this host";
7
- var NO_TAKE = "this host keeps no derived secrets to take";
8
- var UNREADABLE = "a held OAuth credential is unreadable";
9
- var pendingName = (state) => `oauth:grant:${state}`;
10
- var connectionName = (provider) => `oauth:connection:${provider}`;
11
- function parseObject(text) {
12
- let value;
13
- try {
14
- value = JSON.parse(text);
15
- } catch {
16
- throw new Error(UNREADABLE);
17
- }
18
- if (!isJsonObject(value)) throw new Error(UNREADABLE);
19
- return value;
20
- }
21
- function textOf(object, name) {
22
- const value = object[name];
23
- if (typeof value !== "string") throw new Error(UNREADABLE);
24
- return value;
25
- }
26
- function textOrNull(object, name) {
27
- const value = object[name];
28
- if (value === void 0 || value === null) return null;
29
- if (typeof value !== "string") throw new Error(UNREADABLE);
30
- return value;
31
- }
32
- function textList(object, name) {
33
- const value = object[name];
34
- if (!Array.isArray(value)) throw new Error(UNREADABLE);
35
- return value.map((item) => {
36
- if (typeof item !== "string") throw new Error(UNREADABLE);
37
- return item;
38
- });
39
- }
40
- function objectOf(object, name) {
41
- const value = object[name];
42
- if (value === void 0 || !isJsonObject(value)) throw new Error(UNREADABLE);
43
- return value;
44
- }
45
- function grantOf(object) {
46
- return {
47
- provider: textOf(object, "provider"),
48
- redirectUri: textOf(object, "redirectUri"),
49
- verifier: textOf(object, "verifier"),
50
- subject: textOrNull(object, "subject"),
51
- scopes: textList(object, "scopes")
52
- };
53
- }
54
- function rowOf(object, provider) {
55
- const connected = object.connected;
56
- if (typeof connected !== "boolean") throw new Error(UNREADABLE);
57
- return {
58
- provider,
59
- connected,
60
- account: textOf(object, "account"),
61
- avatarUrl: textOf(object, "avatarUrl"),
62
- scope: textList(object, "scope"),
63
- connectedAt: textOf(object, "connectedAt")
64
- };
65
- }
66
- var disconnected = (provider) => ({ provider, connected: false, account: "", avatarUrl: "", scope: [], connectedAt: "" });
67
- function createOAuthPort(options) {
68
- const secrets = () => typeof options.secrets === "function" ? options.secrets() : options.secrets;
69
- const now = options.now ?? Date.now;
70
- const subjects = /* @__PURE__ */ new Map();
71
- const mockTokens = /* @__PURE__ */ new Map();
72
- const mockRefresh = /* @__PURE__ */ new Map();
73
- const metadata = /* @__PURE__ */ new Map();
74
- const caller = (principal) => {
75
- if (principal === void 0 || principal === "") throw new Error(NO_CALLER);
76
- return principal;
77
- };
78
- const durable = async (held) => held.persist !== void 0 && held.durable !== void 0 && held.durable();
79
- const take = async (held, name, principal) => {
80
- if (held.take === void 0) throw new Error(NO_TAKE);
81
- return held.take(name, principal);
82
- };
83
- return {
84
- async answer(ask, principal) {
85
- switch (ask.ask) {
86
- case "pendingPut": {
87
- const held = secrets();
88
- const record = JSON.stringify({ grant: ask.grant, expiresAt: now() + ask.ttlMs });
89
- if (held.hold !== void 0) await held.hold(pendingName(ask.state), record, ask.ttlMs + PENDING_GRACE_MS, void 0);
90
- else await held.set(pendingName(ask.state), record, ask.ttlMs + PENDING_GRACE_MS, void 0);
91
- return { reply: "done" };
92
- }
93
- case "pendingTake": {
94
- const held = secrets();
95
- const name = pendingName(ask.state);
96
- const text = await take(held, name, void 0);
97
- if (text === void 0) return { reply: "taken", taken: { found: "missing" } };
98
- const record = parseObject(text);
99
- const expiresAt = record.expiresAt;
100
- if (typeof expiresAt !== "number") throw new Error(UNREADABLE);
101
- if (expiresAt < now()) return { reply: "taken", taken: { found: "expired" } };
102
- return { reply: "taken", taken: { found: "grant", grant: grantOf(objectOf(record, "grant")) } };
103
- }
104
- case "connectionAvailable":
105
- return { reply: "flag", value: await durable(secrets()) };
106
- case "connectionSave": {
107
- const held = secrets();
108
- if (held.persist === void 0 || !await durable(held)) throw new Error(NO_CONNECTIONS);
109
- const who = caller(principal);
110
- const row = {
111
- provider: ask.provider,
112
- connected: true,
113
- account: ask.grant.subject ?? "",
114
- avatarUrl: "",
115
- scope: ask.grant.scope ?? [],
116
- connectedAt: new Date(now()).toISOString()
117
- };
118
- await held.persist(connectionName(ask.provider), JSON.stringify({ row, grant: ask.grant }), who);
119
- return { reply: "row", row };
120
- }
121
- case "connectionStatus": {
122
- const text = await secrets().get(connectionName(ask.provider), caller(principal));
123
- return { reply: "row", row: text === void 0 ? disconnected(ask.provider) : rowOf(objectOf(parseObject(text), "row"), ask.provider) };
124
- }
125
- case "connectionRemove":
126
- await secrets().forget(connectionName(ask.provider), caller(principal));
127
- return { reply: "row", row: disconnected(ask.provider) };
128
- case "subjectRemember":
129
- subjects.set(ask.accessToken, ask.subject);
130
- return { reply: "done" };
131
- case "subjectLookup":
132
- return { reply: "subject", subject: subjects.get(ask.accessToken) ?? null };
133
- case "subjectForget":
134
- subjects.delete(ask.accessToken);
135
- return { reply: "done" };
136
- case "metadataGet":
137
- return { reply: "metadata", metadata: metadata.get(ask.issuer) ?? null };
138
- case "metadataPut":
139
- metadata.set(ask.issuer, ask.metadata);
140
- return { reply: "done" };
141
- case "clock":
142
- return { reply: "millis", value: now() };
143
- case "consent":
144
- return { reply: "code", code: options.consent === void 0 ? null : await options.consent({ authUrl: ask.authUrl, state: ask.state, redirectUri: ask.redirectUri }) };
145
- case "mockTokenPut":
146
- mockTokens.set(ask.accessToken, { refresh: ask.refreshToken, expiresAt: ask.expiresAtMs, provider: ask.provider });
147
- mockRefresh.set(ask.refreshToken, { access: ask.accessToken, provider: ask.provider });
148
- return { reply: "done" };
149
- case "mockTokenRefresh": {
150
- const old = mockRefresh.get(ask.refreshToken);
151
- if (old === void 0) return { reply: "flag", value: false };
152
- mockTokens.delete(old.access);
153
- const sub = subjects.get(old.access);
154
- subjects.delete(old.access);
155
- if (sub !== void 0) subjects.set(ask.newAccessToken, sub);
156
- mockTokens.set(ask.newAccessToken, { refresh: ask.refreshToken, expiresAt: ask.expiresAtMs, provider: old.provider });
157
- mockRefresh.set(ask.refreshToken, { access: ask.newAccessToken, provider: old.provider });
158
- return { reply: "flag", value: true };
159
- }
160
- case "mockTokenRevoke": {
161
- const held = mockTokens.get(ask.token);
162
- if (held !== void 0) {
163
- mockTokens.delete(ask.token);
164
- mockRefresh.delete(held.refresh);
165
- subjects.delete(ask.token);
166
- return { reply: "flag", value: true };
167
- }
168
- const issued = mockRefresh.get(ask.token);
169
- if (issued !== void 0) {
170
- mockRefresh.delete(ask.token);
171
- mockTokens.delete(issued.access);
172
- subjects.delete(issued.access);
173
- return { reply: "flag", value: true };
174
- }
175
- return { reply: "flag", value: false };
176
- }
177
- case "mockTokenCheck": {
178
- const held = mockTokens.get(ask.accessToken);
179
- if (held === void 0) return { reply: "mockToken", state: "missing", provider: null };
180
- if (now() > held.expiresAt) {
181
- mockTokens.delete(ask.accessToken);
182
- subjects.delete(ask.accessToken);
183
- return { reply: "mockToken", state: "expired", provider: null };
184
- }
185
- return { reply: "mockToken", state: "valid", provider: held.provider };
186
- }
187
- }
188
- }
189
- };
190
- }
191
-
192
- export { PENDING_GRACE_MS, createOAuthPort };
@@ -1,76 +0,0 @@
1
- // src/kernel/lane.ts
2
- var LaneHeldByParkedDispatch = class extends Error {
3
- ticket;
4
- event;
5
- constructor(ticket, event) {
6
- super(
7
- `dispatch #${ticket} (${event}) is parked holding the dispatch lane on this thread; resume or drop it before starting another dispatch`
8
- );
9
- this.name = "LaneHeldByParkedDispatch";
10
- this.ticket = ticket;
11
- this.event = event;
12
- }
13
- };
14
- var DispatchLane = class {
15
- nextTicket = 0;
16
- holder;
17
- depth = 0;
18
- parkedEvent;
19
- waiters = [];
20
- assertCanReenter(turn) {
21
- if (this.holder === turn && this.parkedEvent !== void 0) throw new LaneHeldByParkedDispatch(turn.ticket, this.parkedEvent);
22
- }
23
- async enter(turn) {
24
- const holder = this.holder;
25
- if (holder !== void 0 && turn === holder) {
26
- if (this.parkedEvent !== void 0) {
27
- throw new LaneHeldByParkedDispatch(holder.ticket, this.parkedEvent);
28
- }
29
- this.depth += 1;
30
- return this.guard(holder, false);
31
- }
32
- const own = { ticket: this.nextTicket };
33
- this.nextTicket += 1;
34
- if (this.holder === void 0) {
35
- this.take(own);
36
- } else {
37
- await new Promise((grant) => {
38
- this.waiters.push({ turn: own, grant });
39
- });
40
- }
41
- return this.guard(own, true);
42
- }
43
- take(turn) {
44
- this.holder = turn;
45
- this.depth = 1;
46
- this.parkedEvent = void 0;
47
- }
48
- guard(turn, outer) {
49
- let done = false;
50
- return {
51
- turn,
52
- park: (event) => {
53
- if (!done && outer && this.holder === turn && this.depth === 1) this.parkedEvent = event;
54
- },
55
- resume: () => {
56
- if (!done && outer && this.holder === turn) this.parkedEvent = void 0;
57
- },
58
- release: () => {
59
- if (done) return;
60
- done = true;
61
- if (this.holder !== turn) return;
62
- this.depth -= 1;
63
- if (this.depth > 0) return;
64
- this.holder = void 0;
65
- this.parkedEvent = void 0;
66
- const next = this.waiters.shift();
67
- if (next !== void 0) {
68
- this.take(next.turn);
69
- next.grant();
70
- }
71
- }
72
- };
73
- }
74
- };
75
-
76
- export { DispatchLane, LaneHeldByParkedDispatch };
@@ -1,16 +0,0 @@
1
- import { pipeBehaviors } from './chunk-FQ6IZMIU.js';
2
- import { composeBehaviors } from './chunk-ZCQUUJIF.js';
3
- import { detectLayoutStrategy } from './chunk-EV56K4GB.js';
4
- import { applyEventWiring } from './chunk-MHYSHSRG.js';
5
- import { __export } from './chunk-MLKGABMK.js';
6
-
7
- // src/runtime/effects/composition/index.ts
8
- var composition_exports = {};
9
- __export(composition_exports, {
10
- applyEventWiring: () => applyEventWiring,
11
- composeBehaviors: () => composeBehaviors,
12
- detectLayoutStrategy: () => detectLayoutStrategy,
13
- pipeBehaviors: () => pipeBehaviors
14
- });
15
-
16
- export { composition_exports };
@@ -1,55 +0,0 @@
1
- import { parseOrbitalTraits } from './chunk-SAS5KKCR.js';
2
- import { findEntityAmongOrbitals, orbitalInlineEntities } from '@almadar/core';
3
- import { createLogger } from '@almadar/logger';
4
-
5
- var traitIndexLog = createLogger("almadar:runtime:trait-index");
6
- var parseCache = /* @__PURE__ */ new WeakMap();
7
- function parseOrbitalCached(orbital) {
8
- let cached = parseCache.get(orbital);
9
- if (cached === void 0) {
10
- cached = { traits: parseOrbitalTraits(orbital), entities: orbitalInlineEntities(orbital) };
11
- parseCache.set(orbital, cached);
12
- }
13
- return cached;
14
- }
15
- function buildTraitIndex(orbitals) {
16
- const parsed = orbitals.map((orbital) => ({ orbital, parsed: parseOrbitalCached(orbital).traits }));
17
- const allEntities = orbitals.map((orbital) => parseOrbitalCached(orbital).entities).flat();
18
- const orbitalsView = parsed.map(({ orbital, parsed: p }) => ({ schema: orbital, entity: p.entity }));
19
- const byName = /* @__PURE__ */ new Map();
20
- for (const { orbital, parsed: p } of parsed) {
21
- const { traits, inlineTraits, entity } = p;
22
- for (let i = 0; i < traits.length; i++) {
23
- const traitDef = traits[i];
24
- const irTrait = inlineTraits[i];
25
- const linkedEntityName = irTrait?.linkedEntity;
26
- let traitEntity = entity;
27
- if (linkedEntityName && linkedEntityName !== traitEntity.name) {
28
- const resolved = findEntityAmongOrbitals(allEntities, linkedEntityName);
29
- if (resolved) {
30
- traitEntity = resolved;
31
- } else {
32
- traitIndexLog.warn("linkedEntity:unresolved", {
33
- orbital: orbital.name,
34
- trait: traitDef.name,
35
- linkedEntityName
36
- });
37
- traitEntity = { name: linkedEntityName, fields: [] };
38
- }
39
- }
40
- const isShared = traitEntity.shared === true;
41
- byName.set(traitDef.name, {
42
- traitDef,
43
- irTrait,
44
- entity: traitEntity,
45
- orbitalName: orbital.name,
46
- ...orbital.id !== void 0 ? { orbitalId: orbital.id } : {},
47
- frameKey: isShared ? `$shared::${traitEntity.name}` : traitDef.name,
48
- isSharedEntity: isShared
49
- });
50
- }
51
- }
52
- return { byName, allEntities, orbitals: orbitalsView };
53
- }
54
-
55
- export { buildTraitIndex };
@@ -1,173 +0,0 @@
1
- import { parseCron, cronMinuteKey, cronMatches } from './chunk-CROS2GEX.js';
2
-
3
- // src/runtime/time/TickScheduler.ts
4
- var EVERY_PASS = 0;
5
- var CRON_CHECK_INTERVAL_MS = 1e3;
6
- var TickScheduler = class {
7
- ticks = /* @__PURE__ */ new Map();
8
- nextId = 1;
9
- running = false;
10
- paused = false;
11
- frameHandle = null;
12
- hasRaf;
13
- constructor() {
14
- this.hasRaf = typeof requestAnimationFrame === "function" && typeof cancelAnimationFrame === "function";
15
- }
16
- /**
17
- * Register a tick. `intervalMs <= 0` means "every pass" (a frame-interval
18
- * tick, matching LOLO's `interval: "frame"`). Returns a handle to stop
19
- * just this tick.
20
- */
21
- add(intervalMs, onDue) {
22
- const id = this.nextId++;
23
- this.ticks.set(id, {
24
- kind: "interval",
25
- intervalMs: intervalMs > 0 ? intervalMs : EVERY_PASS,
26
- accumulatedMs: 0,
27
- lastTimestamp: null,
28
- onDue
29
- });
30
- this.ensureRunning();
31
- return {
32
- stop: () => {
33
- this.ticks.delete(id);
34
- this.maybeStop();
35
- }
36
- };
37
- }
38
- /**
39
- * Register a cron-scheduled tick (`ticks { ... every "0 9 * * *" }`).
40
- * Fires at most once per matching calendar minute. Throws if `expression` isn't a valid 5-field cron
41
- * string; callers on a path the compiler has already validated (e.g.
42
- * generated code) won't hit this, but a raw runtime value might.
43
- */
44
- addCron(expression, onDue) {
45
- const fields = parseCron(expression);
46
- const id = this.nextId++;
47
- this.ticks.set(id, {
48
- kind: "cron",
49
- fields,
50
- accumulatedMs: CRON_CHECK_INTERVAL_MS,
51
- // check on the first pass, not after a full second
52
- lastTimestamp: null,
53
- lastFiredMinuteKey: -1,
54
- onDue
55
- });
56
- this.ensureRunning();
57
- return {
58
- stop: () => {
59
- this.ticks.delete(id);
60
- this.maybeStop();
61
- }
62
- };
63
- }
64
- /** Stop every tick and the shared loop. */
65
- stopAll() {
66
- this.ticks.clear();
67
- this.maybeStop();
68
- }
69
- /** True while the scheduler is paused (no tick callback fires and no backlog accumulates). */
70
- get isPaused() {
71
- return this.paused;
72
- }
73
- /**
74
- * Halt the shared loop without dropping registered ticks. No `onDue`
75
- * fires again until `resume()`. A no-op if already paused.
76
- */
77
- pause() {
78
- if (this.paused) return;
79
- this.paused = true;
80
- this.stopLoop();
81
- }
82
- /**
83
- * Restart the shared loop after `pause()`. Every registered tick's phase
84
- * is reset (`lastTimestamp = null`) so the paused duration is never
85
- * counted as elapsed time — the same "first pass just captures the
86
- * timestamp" behavior a freshly `add()`-ed tick gets, which is what keeps
87
- * resume from bursting a backlog of missed beats. A no-op if not paused.
88
- */
89
- resume() {
90
- if (!this.paused) return;
91
- this.paused = false;
92
- for (const tick of this.ticks.values()) {
93
- tick.lastTimestamp = null;
94
- }
95
- if (this.ticks.size > 0) {
96
- this.ensureRunning();
97
- }
98
- }
99
- ensureRunning() {
100
- if (this.running || this.paused) return;
101
- this.running = true;
102
- if (this.hasRaf) {
103
- const loop = (timestamp) => {
104
- if (!this.running) return;
105
- this.advance(timestamp);
106
- this.frameHandle = requestAnimationFrame(loop);
107
- };
108
- this.frameHandle = requestAnimationFrame(loop);
109
- } else {
110
- this.frameHandle = setInterval(() => this.advance(Date.now()), 16);
111
- }
112
- }
113
- maybeStop() {
114
- if (this.ticks.size > 0 || !this.running) return;
115
- this.stopLoop();
116
- }
117
- /** Cancel the active rAF/interval loop, if any, and clear the running flag. */
118
- stopLoop() {
119
- this.running = false;
120
- if (this.frameHandle !== null) {
121
- if (this.hasRaf) {
122
- cancelAnimationFrame(this.frameHandle);
123
- } else {
124
- clearInterval(this.frameHandle);
125
- }
126
- this.frameHandle = null;
127
- }
128
- }
129
- advance(timestamp) {
130
- for (const tick of this.ticks.values()) {
131
- if (tick.kind === "cron") {
132
- this.advanceCron(tick, timestamp);
133
- continue;
134
- }
135
- if (tick.intervalMs <= EVERY_PASS) {
136
- tick.onDue();
137
- continue;
138
- }
139
- if (tick.lastTimestamp === null) {
140
- tick.lastTimestamp = timestamp;
141
- continue;
142
- }
143
- tick.accumulatedMs += timestamp - tick.lastTimestamp;
144
- tick.lastTimestamp = timestamp;
145
- if (tick.accumulatedMs >= tick.intervalMs) {
146
- tick.onDue();
147
- tick.accumulatedMs = tick.accumulatedMs % tick.intervalMs;
148
- }
149
- }
150
- }
151
- /** Cron ticks check calendar-match at most once a second, deduped per matching minute. */
152
- advanceCron(tick, timestamp) {
153
- if (tick.lastTimestamp === null) {
154
- tick.lastTimestamp = timestamp;
155
- return;
156
- }
157
- tick.accumulatedMs += timestamp - tick.lastTimestamp;
158
- tick.lastTimestamp = timestamp;
159
- if (tick.accumulatedMs < CRON_CHECK_INTERVAL_MS) return;
160
- tick.accumulatedMs = 0;
161
- const now = /* @__PURE__ */ new Date();
162
- const minuteKey = cronMinuteKey(now);
163
- if (minuteKey !== tick.lastFiredMinuteKey && cronMatches(tick.fields, now)) {
164
- tick.lastFiredMinuteKey = minuteKey;
165
- tick.onDue();
166
- }
167
- }
168
- };
169
- function createTickScheduler() {
170
- return new TickScheduler();
171
- }
172
-
173
- export { TickScheduler, createTickScheduler };
@@ -1,49 +0,0 @@
1
- // src/runtime/time/cron.ts
2
- function parseCronField(field, min, max) {
3
- const values = /* @__PURE__ */ new Set();
4
- for (const part of field.split(",")) {
5
- if (part === "*") {
6
- for (let i = min; i <= max; i++) values.add(i);
7
- } else if (part.includes("/")) {
8
- const [range, stepStr] = part.split("/");
9
- const step = parseInt(stepStr, 10);
10
- const start = range === "*" ? min : parseInt(range, 10);
11
- for (let i = start; i <= max; i += step) values.add(i);
12
- } else if (part.includes("-")) {
13
- const [lo, hi] = part.split("-").map(Number);
14
- for (let i = lo; i <= hi; i++) values.add(i);
15
- } else {
16
- values.add(parseInt(part, 10));
17
- }
18
- }
19
- return values;
20
- }
21
- function parseCron(expression) {
22
- const parts = expression.trim().split(/\s+/);
23
- if (parts.length !== 5) {
24
- throw new Error(`Invalid cron expression (expected 5 fields): ${expression}`);
25
- }
26
- return {
27
- minute: parseCronField(parts[0], 0, 59),
28
- hour: parseCronField(parts[1], 0, 23),
29
- day: parseCronField(parts[2], 1, 31),
30
- month: parseCronField(parts[3], 1, 12),
31
- weekday: parseCronField(parts[4], 0, 6)
32
- };
33
- }
34
- function isValidCronExpression(expression) {
35
- try {
36
- parseCron(expression);
37
- return true;
38
- } catch {
39
- return false;
40
- }
41
- }
42
- function cronMatches(fields, date) {
43
- return fields.minute.has(date.getMinutes()) && fields.hour.has(date.getHours()) && fields.day.has(date.getDate()) && fields.month.has(date.getMonth() + 1) && fields.weekday.has(date.getDay());
44
- }
45
- function cronMinuteKey(date) {
46
- return date.getFullYear() * 1e8 + date.getMonth() * 1e6 + date.getDate() * 1e4 + date.getHours() * 100 + date.getMinutes();
47
- }
48
-
49
- export { cronMatches, cronMinuteKey, isValidCronExpression, parseCron, parseCronField };