@almadar/shell-web 1.2.1 → 1.3.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 (77) hide show
  1. package/dist/AvlGlyph-N2MSWT7H.js +5 -0
  2. package/dist/{AvlStateMachine-KVZMFHFU.js → AvlStateMachine-HDWKFV7C.js} +3 -3
  3. package/dist/AvlTransitionDetail-CRMZLMFV.js +10 -0
  4. package/dist/AvlTransitionExplainer-NJLDP7X5.js +11 -0
  5. package/dist/BehaviorView-EFKTS3KZ.js +10 -0
  6. package/dist/{FileTree-B3GDAjaQ.d.ts → FileTree-CSdbAdcJ.d.ts} +8 -0
  7. package/dist/FlowCanvas-S3ODHQXS.js +23 -0
  8. package/dist/{GameAudioProvider-BgWOOYT3.d.ts → GameAudioProvider-B8FBcGVE.d.ts} +1 -1
  9. package/dist/{KernelEngineContext-BPx-q0iw.d.ts → KernelEngineContext-6l6vkc50.d.ts} +1 -1
  10. package/dist/{LayersPanel-PSXI4EHG.js → LayersPanel-YHXNS36U.js} +4 -4
  11. package/dist/ModuleCard-6UW7YBAH.js +6 -0
  12. package/dist/OrbInspector-RQU5P2T6.js +23 -0
  13. package/dist/OrbPreview-V4VLWNMT.css +1754 -0
  14. package/dist/OrbPreview-WKC3ORIK.js +23 -0
  15. package/dist/{Select-BJ8Fgc8A.d.ts → Select-DuX0Gvwo.d.ts} +14 -8
  16. package/dist/UISlotRenderer-7IGRYWII.js +23 -0
  17. package/dist/auth/react/index.js +4 -0
  18. package/dist/avl/index.d.ts +2 -2
  19. package/dist/avl/index.js +25 -25
  20. package/dist/{chunk-LKL5RULQ.js → chunk-3OF2X6GG.js} +2 -2
  21. package/dist/{chunk-V5SVGUYN.js → chunk-3WSTUUJ7.js} +1 -1
  22. package/dist/{chunk-B23EZH2P.js → chunk-4IFO6QJL.js} +3 -3
  23. package/dist/{chunk-RDPELAFQ.js → chunk-4UAAP6ZN.js} +2 -2
  24. package/dist/{chunk-LINJRTNB.js → chunk-6MZ224GN.js} +2 -2
  25. package/dist/{chunk-3YUMGEEW.js → chunk-AYQKZFUH.js} +1 -1
  26. package/dist/{chunk-3DA36FOA.js → chunk-BY2UJWVR.js} +1 -1
  27. package/dist/{chunk-S3LS3B7N.js → chunk-CB4POLGP.js} +1 -1
  28. package/dist/{chunk-2LNXLMK3.js → chunk-FZOX7XTU.js} +41 -41
  29. package/dist/{chunk-ZDRDJKYB.js → chunk-MXN32OVV.js} +212 -20
  30. package/dist/{chunk-TAEOMNDK.js → chunk-NIOQT2IE.js} +44914 -44206
  31. package/dist/{chunk-CCO2ZH7F.js → chunk-NVSUTIJ2.js} +2 -2
  32. package/dist/{chunk-DPDKBY6Z.js → chunk-OEWVBYW5.js} +1 -0
  33. package/dist/{chunk-UFQLHCFJ.js → chunk-OHWEWQL3.js} +1 -1
  34. package/dist/{chunk-D5FJU4XC.js → chunk-OOG33EGF.js} +46 -14
  35. package/dist/{chunk-AU7O65OX.js → chunk-OXHXISFA.js} +1 -1
  36. package/dist/{chunk-PWXZN5G5.js → chunk-PD5QUVRE.js} +2 -2
  37. package/dist/{chunk-6RXP5ZXE.js → chunk-PHIQOASV.js} +5 -5
  38. package/dist/{chunk-GHAF7QUD.js → chunk-QZ6TDP6I.js} +1 -1
  39. package/dist/{chunk-JEN4EIUF.js → chunk-RCB4CKRK.js} +1 -1
  40. package/dist/{chunk-AL2XXMYR.js → chunk-RQH6O76X.js} +20 -6
  41. package/dist/{chunk-7UCL26QB.js → chunk-TJEB4PII.js} +3 -3
  42. package/dist/{chunk-KTYOYEVA.js → chunk-YU2ZNLGI.js} +1 -1
  43. package/dist/components/index.d.ts +295 -22
  44. package/dist/components/index.js +27 -22
  45. package/dist/context/index.js +3 -3
  46. package/dist/core.d.ts +23 -6
  47. package/dist/core.js +1 -1
  48. package/dist/{fx-Bx5RqplG.d.ts → fx-Bc3yEVED.d.ts} +2 -2
  49. package/dist/hooks/index.js +4 -4
  50. package/dist/index.d.ts +18 -5
  51. package/dist/index.js +4 -4
  52. package/dist/{kernel-client-NMZ56JVU.js → kernel-client-NM6S72DO.js} +74 -33
  53. package/dist/{kernel-wire-CRsHtLsf.d.ts → kernel-wire-Ds7xSZzx.d.ts} +6 -0
  54. package/dist/lib/index.d.ts +2 -2
  55. package/dist/lib/index.js +3 -3
  56. package/dist/providers/index.d.ts +5 -5
  57. package/dist/providers/index.js +15 -15
  58. package/dist/runtime/index.d.ts +6 -2
  59. package/dist/runtime/index.js +14 -14
  60. package/dist/ssr/index.cjs +27 -4
  61. package/dist/ssr/index.d.cts +6 -0
  62. package/dist/ssr/index.d.ts +6 -0
  63. package/dist/ssr/index.js +27 -4
  64. package/dist/test-support.js +2 -2
  65. package/dist/{verificationRegistry-BLuQU1JV.d.ts → verificationRegistry-Dz5N0oxx.d.ts} +199 -8
  66. package/package.json +9 -9
  67. package/src/core/locales/ar.json +8 -1
  68. package/src/core/locales/en.json +8 -1
  69. package/src/core/locales/sl.json +8 -1
  70. package/dist/AvlGlyph-KZMJDBEB.js +0 -5
  71. package/dist/AvlTransitionDetail-7DVGV27I.js +0 -10
  72. package/dist/AvlTransitionExplainer-RMJ5LQLK.js +0 -11
  73. package/dist/BehaviorView-EYRPME67.js +0 -10
  74. package/dist/FlowCanvas-J54627TC.js +0 -23
  75. package/dist/ModuleCard-TNRLL45H.js +0 -6
  76. package/dist/OrbInspector-UBEQWWZ2.js +0 -23
  77. package/dist/UISlotRenderer-5OURMAP2.js +0 -23
@@ -1,30 +1,110 @@
1
1
  import { __export, __reExport } from './chunk-G7DCAZ22.js';
2
+ import { instancesForLocale, orbitalInlineEntities, storesRowsInBrowser, isRoutePage, tickEventKey, isJsonObject } from '@almadar/core';
3
+ import { createLogger, isLogLevelEnabled } from '@almadar/logger';
4
+ import { HostAskError, consentFromRedirect, performHostAnswer, hostAskReturn } from '@almadar/shell-runtime/kernel/host';
2
5
  import { NativeMemoryPersistenceAdapter } from '@almadar/shell-runtime/persistence/native-memory';
3
6
  import * as local_store_transport_star from '@almadar/shell-runtime/runtime/evaluation/local-store-transport';
4
7
  import { openLocalKernel as openLocalKernel$1 } from '@almadar/shell-runtime/runtime/evaluation/local-store-transport';
5
8
  import { readPageFacts } from '@almadar/shell-browser/page-facts';
6
- import { instancesForLocale, orbitalInlineEntities, storesRowsInBrowser, isRoutePage, tickEventKey, isJsonObject } from '@almadar/core';
7
- import { createLogger, isLogLevelEnabled } from '@almadar/logger';
8
- import { HostAskError, consentFromRedirect, performHostAnswer, hostAskReturn } from '@almadar/shell-runtime/kernel/host';
9
9
  import { dispatchDeclaredInput } from '@almadar/shell-runtime/client/declared-input-dispatch';
10
10
  import { IndexedDbPersistence } from '@almadar/shell-browser/storage';
11
11
  export { eventRouteKey } from '@almadar/shell-runtime/runtime/events/identity/routing';
12
12
  export { createResidenceTransport } from '@almadar/shell-runtime/runtime/evaluation/residence-transport';
13
13
 
14
- function hasMemoryStore(kernel) {
15
- return "MemoryStore" in kernel;
14
+ var context;
15
+ var buffers = /* @__PURE__ */ new Map();
16
+ var voices = /* @__PURE__ */ new Map();
17
+ function audioContext() {
18
+ if (context !== void 0) return context;
19
+ if (typeof AudioContext === "undefined") return void 0;
20
+ context = new AudioContext();
21
+ return context;
22
+ }
23
+ function load(ctx, source) {
24
+ const cached = buffers.get(source);
25
+ if (cached !== void 0) return cached;
26
+ const pending = (async () => {
27
+ const response = await fetch(source);
28
+ if (!response.ok) throw new Error(`audio/schedule: ${source} did not load (${response.status})`);
29
+ return ctx.decodeAudioData(await response.arrayBuffer());
30
+ })();
31
+ buffers.set(source, pending);
32
+ pending.catch(() => buffers.delete(source));
33
+ return pending;
34
+ }
35
+ function begin(ctx, buffer, spec) {
36
+ const previous = voices.get(spec.key);
37
+ if (previous !== void 0) previous.source.stop(spec.at);
38
+ const source = ctx.createBufferSource();
39
+ const gain = ctx.createGain();
40
+ source.buffer = buffer;
41
+ source.playbackRate.value = spec.rate;
42
+ gain.gain.value = spec.gain;
43
+ source.connect(gain);
44
+ gain.connect(ctx.destination);
45
+ const voice = { source, gain, gainValue: spec.gain, rateValue: spec.rate, ended: false };
46
+ voices.set(spec.key, voice);
47
+ source.onended = () => {
48
+ voice.ended = true;
49
+ };
50
+ if (spec.duration !== void 0) source.start(spec.at, spec.offset, spec.duration);
51
+ else source.start(spec.at, spec.offset);
52
+ }
53
+ async function scheduleAudio(commands) {
54
+ const ctx = audioContext();
55
+ if (ctx === void 0) throw new HostAskError("unavailable", "audio/schedule: this environment has no AudioContext");
56
+ const known = new Set(voices.keys());
57
+ for (const command of commands) {
58
+ if ("start" in command) known.add(command.start.key);
59
+ else if ("stop" in command) {
60
+ if (!known.has(command.stop.key)) throw new HostAskError("invalid", `audio/schedule: no voice named ${command.stop.key} was started`);
61
+ known.delete(command.stop.key);
62
+ } else if (!known.has(command.ramp.key)) throw new HostAskError("invalid", `audio/schedule: no voice named ${command.ramp.key} was started`);
63
+ }
64
+ try {
65
+ await ctx.resume();
66
+ const decoded = /* @__PURE__ */ new Map();
67
+ for (const command of commands) {
68
+ if ("start" in command && !decoded.has(command.start.source)) decoded.set(command.start.source, await load(ctx, command.start.source));
69
+ }
70
+ for (const command of commands) {
71
+ if ("start" in command) {
72
+ const buffer = decoded.get(command.start.source);
73
+ if (buffer === void 0) throw new HostAskError("unavailable", `audio/schedule: ${command.start.source} was not decoded`);
74
+ begin(ctx, buffer, command.start);
75
+ continue;
76
+ }
77
+ const key = "stop" in command ? command.stop.key : command.ramp.key;
78
+ const voice = voices.get(key);
79
+ if (voice === void 0) throw new HostAskError("invalid", `audio/schedule: no voice named ${key} was started`);
80
+ if ("stop" in command) {
81
+ if (!voice.ended) voice.source.stop(command.stop.at);
82
+ voices.delete(key);
83
+ continue;
84
+ }
85
+ if (voice.ended) continue;
86
+ const { param, value, at, endAt, curve } = command.ramp;
87
+ const target = param === "gain" ? voice.gain.gain : voice.source.playbackRate;
88
+ target.setValueAtTime(param === "gain" ? voice.gainValue : voice.rateValue, at);
89
+ if (curve === "linear") target.linearRampToValueAtTime(value, endAt);
90
+ else target.exponentialRampToValueAtTime(value, endAt);
91
+ if (param === "gain") voice.gainValue = value;
92
+ else voice.rateValue = value;
93
+ }
94
+ } catch (error) {
95
+ if (error instanceof HostAskError) throw error;
96
+ throw new HostAskError("unavailable", error instanceof Error ? error.message : String(error));
97
+ }
16
98
  }
17
- function nativeMemoryPersistence(kernel) {
18
- if (!hasMemoryStore(kernel)) throw new Error("nativeMemoryPersistence: this kernel module exports no MemoryStore; install a kernel build that carries it");
19
- return new NativeMemoryPersistenceAdapter(new kernel.MemoryStore());
99
+ async function readAudioClock() {
100
+ const ctx = audioContext();
101
+ if (ctx === void 0) throw new HostAskError("unavailable", "audio/clock: this environment has no AudioContext");
102
+ if (typeof ctx.getOutputTimestamp === "function") {
103
+ const { contextTime, performanceTime } = ctx.getOutputTimestamp();
104
+ if (contextTime !== void 0 && performanceTime !== void 0) return { audio: contextTime, wall: performance.timeOrigin + performanceTime };
105
+ }
106
+ return { audio: ctx.currentTime, wall: performance.timeOrigin + performance.now() };
20
107
  }
21
-
22
- // src/runtime/evaluation/local-store-transport.ts
23
- var local_store_transport_exports = {};
24
- __export(local_store_transport_exports, {
25
- openLocalKernel: () => openLocalKernel
26
- });
27
- __reExport(local_store_transport_exports, local_store_transport_star);
28
108
  var POLL_MS = 250;
29
109
  function consentByPopup(env) {
30
110
  return async (request) => {
@@ -94,6 +174,8 @@ var webHostActions = {
94
174
  get signIn() {
95
175
  return signInHost;
96
176
  },
177
+ audioSchedule: scheduleAudio,
178
+ audioClock: readAudioClock,
97
179
  get consent() {
98
180
  return consentHost ?? (typeof window === "undefined" ? void 0 : consentByPopup(browserConsentEnv(window)));
99
181
  }
@@ -110,11 +192,13 @@ function streamTrace(args, completion, dispatch, source) {
110
192
  const named = options !== void 0 && options !== null && isJsonObject(options) ? options["traits"] : void 0;
111
193
  const traits = Array.isArray(named) ? named.flatMap((t) => typeof t === "string" ? [t] : []) : [];
112
194
  if (traits.length === 0) return refuse("program/live trace: name the traits it observes in `traits`");
195
+ const cost = options !== void 0 && options !== null && isJsonObject(options) ? options["cost"] : void 0;
196
+ if (cost !== void 0 && cost !== null && typeof cost !== "boolean") return refuse("program/live trace: cost must be a boolean when supplied");
113
197
  if (source === void 0 || dispatch === void 0) return refuse("program/live trace: this host has no kernel trace to stream");
114
198
  if (traceStreams.has(key)) return refuse(`key ${key} already has a stream open`);
115
199
  traceStreams.set(key, source(traits, (item) => {
116
200
  void dispatch(trait, onMessage, { ...item, key, ...completion.entityId !== void 0 ? { entityId: completion.entityId } : {} }).catch((error) => log.error("trace item return failed", { trait, key, error: error.message }));
117
- }));
201
+ }, cost === true));
118
202
  }
119
203
  function cancelStreams(args) {
120
204
  const named = args[0];
@@ -138,8 +222,20 @@ async function answerHostAsk(op, args, completion, dispatch, trace) {
138
222
  }
139
223
  await dispatch(returned.trait, returned.event, returned.entityId !== void 0 ? { ...returned.payload, entityId: returned.entityId } : returned.payload);
140
224
  }
225
+ function hasMemoryStore(kernel) {
226
+ return "MemoryStore" in kernel;
227
+ }
228
+ function nativeMemoryPersistence(kernel) {
229
+ if (!hasMemoryStore(kernel)) throw new Error("nativeMemoryPersistence: this kernel module exports no MemoryStore; install a kernel build that carries it");
230
+ return new NativeMemoryPersistenceAdapter(new kernel.MemoryStore());
231
+ }
141
232
 
142
233
  // src/runtime/evaluation/local-store-transport.ts
234
+ var local_store_transport_exports = {};
235
+ __export(local_store_transport_exports, {
236
+ openLocalKernel: () => openLocalKernel
237
+ });
238
+ __reExport(local_store_transport_exports, local_store_transport_star);
143
239
  function openLocalKernel(options) {
144
240
  return openLocalKernel$1({ ...options, pageFacts: options.pageFacts ?? readPageFacts, hostActions: options.hostActions ?? webHostActions });
145
241
  }
@@ -205,14 +301,110 @@ async function persistedMemory(kernel, database, entities, locale) {
205
301
  function browserStoreName(appName, locale) {
206
302
  return locale !== void 0 ? `almadar:${appName}:${locale}` : `almadar:${appName}`;
207
303
  }
208
- async function openBrowserStore(databaseName, orbitals, factory) {
304
+ function tableOf(entity) {
305
+ return entity.collection ?? entity.name;
306
+ }
307
+ async function moveTypeStores(factory, databaseName, entities) {
308
+ const collections = new Set(entities.map(tableOf));
309
+ const current = await new Promise((resolve, reject) => {
310
+ const req = factory.open(databaseName);
311
+ req.onsuccess = () => resolve(req.result);
312
+ req.onerror = () => reject(req.error);
313
+ });
314
+ const stale = entities.filter((e) => tableOf(e) !== e.name && !collections.has(e.name) && current.objectStoreNames.contains(e.name));
315
+ const next = current.version + 1;
316
+ current.close();
317
+ if (stale.length === 0) return;
318
+ await new Promise((resolve, reject) => {
319
+ const req = factory.open(databaseName, next);
320
+ req.onupgradeneeded = () => {
321
+ const db = req.result;
322
+ const tx = req.transaction;
323
+ if (tx === null) return;
324
+ const moveOne = (index) => {
325
+ const entity = stale[index];
326
+ if (entity === void 0) return;
327
+ const target = tableOf(entity);
328
+ if (!db.objectStoreNames.contains(target)) db.createObjectStore(target, { keyPath: "id" });
329
+ const old = tx.objectStore(entity.name);
330
+ const destination = tx.objectStore(target);
331
+ const rows = old.getAll();
332
+ rows.onsuccess = () => {
333
+ const keys = destination.getAllKeys();
334
+ keys.onsuccess = () => {
335
+ const present = new Set(keys.result);
336
+ for (const row of rows.result) if (!present.has(row.id)) destination.put(row);
337
+ db.deleteObjectStore(entity.name);
338
+ moveOne(index + 1);
339
+ };
340
+ };
341
+ };
342
+ moveOne(0);
343
+ };
344
+ req.onsuccess = () => {
345
+ req.result.close();
346
+ resolve();
347
+ };
348
+ req.onerror = () => reject(req.error);
349
+ req.onblocked = () => reject(new Error(`browser store "${databaseName}" is open in another context and cannot be upgraded`));
350
+ });
351
+ }
352
+ async function adoptDatabase(factory, formerName, entities, target) {
353
+ await moveTypeStores(factory, formerName, entities);
354
+ const tables = [...new Set(entities.map(tableOf))];
355
+ const former = await new Promise((resolve, reject) => {
356
+ const req = factory.open(formerName);
357
+ req.onsuccess = () => resolve(req.result);
358
+ req.onerror = () => reject(req.error);
359
+ });
360
+ const held = /* @__PURE__ */ new Map();
361
+ try {
362
+ for (const table of tables) {
363
+ if (!former.objectStoreNames.contains(table)) continue;
364
+ const rows = await new Promise((resolve, reject) => {
365
+ const req = former.transaction(table, "readonly").objectStore(table).getAll();
366
+ req.onsuccess = () => resolve(req.result);
367
+ req.onerror = () => reject(req.error);
368
+ });
369
+ held.set(table, rows);
370
+ }
371
+ } finally {
372
+ former.close();
373
+ }
374
+ for (const [table, rows] of held) {
375
+ const present = new Set((await target.list(table)).map((row) => row.id));
376
+ for (const row of rows) if (!present.has(row.id)) await target.create(table, row);
377
+ }
378
+ await new Promise((resolve, reject) => {
379
+ const req = factory.deleteDatabase(formerName);
380
+ req.onsuccess = () => resolve();
381
+ req.onerror = () => reject(req.error);
382
+ req.onblocked = () => reject(new Error(`browser store "${formerName}" is open in another context and cannot be removed`));
383
+ });
384
+ }
385
+ async function openBrowserStore(databaseName, orbitals, factory, formerDatabaseName) {
209
386
  const entities = orbitals.flatMap(orbitalInlineEntities).filter(storesRowsInBrowser);
210
387
  if (entities.length === 0) return null;
211
- return IndexedDbPersistence.open({
388
+ const idb = factory ?? globalThis.indexedDB;
389
+ if (!idb) throw new Error("IndexedDbPersistence: this environment has no IndexedDB");
390
+ await moveTypeStores(idb, databaseName, entities);
391
+ const tables = new Map(entities.map((e) => [e.name, tableOf(e)]));
392
+ const table = (entityType) => tables.get(entityType) ?? entityType;
393
+ const database = await IndexedDbPersistence.open({
212
394
  databaseName,
213
- entityTypes: entities.map((e) => e.name),
214
- ...factory !== void 0 ? { factory } : {}
395
+ entityTypes: [...new Set(tables.values())],
396
+ factory: idb
215
397
  });
398
+ if (formerDatabaseName !== void 0 && formerDatabaseName !== databaseName) {
399
+ await adoptDatabase(idb, formerDatabaseName, entities, database);
400
+ }
401
+ return {
402
+ create: (entityType, data) => database.create(table(entityType), data),
403
+ delete: (entityType, id) => database.delete(table(entityType), id),
404
+ list: (entityType) => database.list(table(entityType)),
405
+ changes: () => database.changes(),
406
+ close: () => database.close()
407
+ };
216
408
  }
217
409
  function browserEntities(orbitals) {
218
410
  return orbitals.flatMap(orbitalInlineEntities).filter(storesRowsInBrowser);