@spearwolf/shadow-objects 0.32.0 → 0.34.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 (213) hide show
  1. package/CHANGELOG.md +333 -10
  2. package/README.md +100 -20
  3. package/bundle.js +5 -54
  4. package/package.json +7 -3
  5. package/src/ChangeTrailRefusedError.d.ts +27 -0
  6. package/src/ChangeTrailRefusedError.d.ts.map +1 -0
  7. package/src/ChangeTrailRefusedError.js +12 -0
  8. package/src/ChangeTrailRefusedError.js.map +7 -0
  9. package/src/EntityUuidInUseError.d.ts +19 -0
  10. package/src/EntityUuidInUseError.d.ts.map +1 -0
  11. package/src/EntityUuidInUseError.js +11 -0
  12. package/src/EntityUuidInUseError.js.map +7 -0
  13. package/src/WorkerTimeoutError.d.ts +25 -0
  14. package/src/WorkerTimeoutError.d.ts.map +1 -0
  15. package/src/WorkerTimeoutError.js +12 -0
  16. package/src/WorkerTimeoutError.js.map +7 -0
  17. package/src/bundle.d.ts +1 -1
  18. package/src/bundle.d.ts.map +1 -1
  19. package/src/bundle.js +1 -1
  20. package/src/bundle.js.map +2 -2
  21. package/src/constants.d.ts +9 -2
  22. package/src/constants.d.ts.map +1 -1
  23. package/src/constants.js +1 -1
  24. package/src/constants.js.map +2 -2
  25. package/src/create-worker.bundle.d.ts +1 -1
  26. package/src/create-worker.bundle.d.ts.map +1 -1
  27. package/src/create-worker.bundle.js.map +1 -1
  28. package/src/create-worker.d.ts +1 -1
  29. package/src/create-worker.d.ts.map +1 -1
  30. package/src/create-worker.js.map +1 -1
  31. package/src/elements/ShaeElement.d.ts +70 -2
  32. package/src/elements/ShaeElement.d.ts.map +1 -1
  33. package/src/elements/ShaeElement.js +129 -25
  34. package/src/elements/ShaeElement.js.map +3 -3
  35. package/src/elements/ShaeEntElement.d.ts +43 -5
  36. package/src/elements/ShaeEntElement.d.ts.map +1 -1
  37. package/src/elements/ShaeEntElement.js +399 -170
  38. package/src/elements/ShaeEntElement.js.map +2 -2
  39. package/src/elements/ShaeLifecycleElement.d.ts +71 -0
  40. package/src/elements/ShaeLifecycleElement.d.ts.map +1 -0
  41. package/src/elements/ShaeLifecycleElement.js +83 -0
  42. package/src/elements/ShaeLifecycleElement.js.map +7 -0
  43. package/src/elements/ShaePropElement.d.ts +57 -7
  44. package/src/elements/ShaePropElement.d.ts.map +1 -1
  45. package/src/elements/ShaePropElement.js +241 -220
  46. package/src/elements/ShaePropElement.js.map +2 -2
  47. package/src/elements/ShaeWorkerElement.d.ts +49 -5
  48. package/src/elements/ShaeWorkerElement.d.ts.map +1 -1
  49. package/src/elements/ShaeWorkerElement.js +230 -74
  50. package/src/elements/ShaeWorkerElement.js.map +2 -2
  51. package/src/elements/constants.d.ts +6 -0
  52. package/src/elements/constants.d.ts.map +1 -1
  53. package/src/elements/constants.js +12 -0
  54. package/src/elements/constants.js.map +2 -2
  55. package/src/elements/deferredTeardown.d.ts +24 -0
  56. package/src/elements/deferredTeardown.d.ts.map +1 -0
  57. package/src/elements/deferredTeardown.js +30 -0
  58. package/src/elements/deferredTeardown.js.map +7 -0
  59. package/src/elements/displayContentsRule.d.ts +25 -0
  60. package/src/elements/displayContentsRule.d.ts.map +1 -0
  61. package/src/elements/displayContentsRule.js +37 -0
  62. package/src/elements/displayContentsRule.js.map +7 -0
  63. package/src/elements/events.d.ts +10 -7
  64. package/src/elements/events.d.ts.map +1 -1
  65. package/src/elements/forwardCustomEvents.d.ts +19 -0
  66. package/src/elements/forwardCustomEvents.d.ts.map +1 -0
  67. package/src/elements/forwardCustomEvents.js +47 -0
  68. package/src/elements/forwardCustomEvents.js.map +7 -0
  69. package/src/elements/hostedSlots.d.ts +36 -0
  70. package/src/elements/hostedSlots.d.ts.map +1 -0
  71. package/src/elements/hostedSlots.js +118 -0
  72. package/src/elements/hostedSlots.js.map +7 -0
  73. package/src/elements/parentRemoval.d.ts +18 -0
  74. package/src/elements/parentRemoval.d.ts.map +1 -0
  75. package/src/elements/parentRemoval.js +60 -0
  76. package/src/elements/parentRemoval.js.map +7 -0
  77. package/src/elements/propValueConverters.d.ts +3 -0
  78. package/src/elements/propValueConverters.d.ts.map +1 -0
  79. package/src/elements/propValueConverters.js +54 -0
  80. package/src/elements/propValueConverters.js.map +7 -0
  81. package/src/elements/requestEntAncestor.d.ts +32 -0
  82. package/src/elements/requestEntAncestor.d.ts.map +1 -0
  83. package/src/elements/requestEntAncestor.js +16 -0
  84. package/src/elements/requestEntAncestor.js.map +7 -0
  85. package/src/elements.js.map +1 -1
  86. package/src/in-the-dark/Entity.d.ts +113 -3
  87. package/src/in-the-dark/Entity.d.ts.map +1 -1
  88. package/src/in-the-dark/Entity.js +292 -63
  89. package/src/in-the-dark/Entity.js.map +3 -3
  90. package/src/in-the-dark/Kernel.d.ts +81 -17
  91. package/src/in-the-dark/Kernel.d.ts.map +1 -1
  92. package/src/in-the-dark/Kernel.js +449 -392
  93. package/src/in-the-dark/Kernel.js.map +3 -3
  94. package/src/in-the-dark/Registry.d.ts +1 -1
  95. package/src/in-the-dark/Registry.d.ts.map +1 -1
  96. package/src/in-the-dark/Registry.js +99 -26
  97. package/src/in-the-dark/Registry.js.map +2 -2
  98. package/src/in-the-dark/ShadowObject.d.ts +1 -1
  99. package/src/in-the-dark/ShadowObject.d.ts.map +1 -1
  100. package/src/in-the-dark/ShadowObject.js +3 -2
  101. package/src/in-the-dark/ShadowObject.js.map +2 -2
  102. package/src/in-the-dark/ShadowObjectCreationScope.d.ts +126 -0
  103. package/src/in-the-dark/ShadowObjectCreationScope.d.ts.map +1 -0
  104. package/src/in-the-dark/ShadowObjectCreationScope.js +596 -0
  105. package/src/in-the-dark/ShadowObjectCreationScope.js.map +7 -0
  106. package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
  107. package/src/in-the-dark/SignalsPath.js +2 -2
  108. package/src/in-the-dark/SignalsPath.js.map +2 -2
  109. package/src/in-the-dark/events.js.map +1 -1
  110. package/src/in-the-dark/importModule.d.ts +7 -0
  111. package/src/in-the-dark/importModule.d.ts.map +1 -1
  112. package/src/in-the-dark/importModule.js +8 -5
  113. package/src/in-the-dark/importModule.js.map +2 -2
  114. package/src/index.d.ts +7 -1
  115. package/src/index.d.ts.map +1 -1
  116. package/src/index.js +5 -1
  117. package/src/index.js.map +2 -2
  118. package/src/shadow-objects.d.ts +2 -0
  119. package/src/shadow-objects.d.ts.map +1 -1
  120. package/src/shadow-objects.js +2 -0
  121. package/src/shadow-objects.js.map +2 -2
  122. package/src/shadow-objects.worker.js +0 -1
  123. package/src/shadow-objects.worker.js.map +2 -2
  124. package/src/shae-ent.js.map +1 -1
  125. package/src/shae-prop.js +2 -2
  126. package/src/shae-prop.js.map +2 -2
  127. package/src/shae-worker.js.map +1 -1
  128. package/src/types.d.ts +39 -8
  129. package/src/types.d.ts.map +1 -1
  130. package/src/utils/ConsoleLogger.d.ts +45 -10
  131. package/src/utils/ConsoleLogger.d.ts.map +1 -1
  132. package/src/utils/ConsoleLogger.js +54 -28
  133. package/src/utils/ConsoleLogger.js.map +2 -2
  134. package/src/utils/FrameLoop.d.ts +42 -3
  135. package/src/utils/FrameLoop.d.ts.map +1 -1
  136. package/src/utils/FrameLoop.js +71 -12
  137. package/src/utils/FrameLoop.js.map +2 -2
  138. package/src/utils/MicrotaskCollector.d.ts +45 -0
  139. package/src/utils/MicrotaskCollector.d.ts.map +1 -0
  140. package/src/utils/MicrotaskCollector.js +33 -0
  141. package/src/utils/MicrotaskCollector.js.map +7 -0
  142. package/src/utils/MicrotaskGate.d.ts +17 -0
  143. package/src/utils/MicrotaskGate.d.ts.map +1 -0
  144. package/src/utils/MicrotaskGate.js +20 -0
  145. package/src/utils/MicrotaskGate.js.map +7 -0
  146. package/src/utils/array-utils.js.map +1 -1
  147. package/src/utils/attr-utils.d.ts +6 -0
  148. package/src/utils/attr-utils.d.ts.map +1 -1
  149. package/src/utils/attr-utils.js +4 -2
  150. package/src/utils/attr-utils.js.map +2 -2
  151. package/src/utils/constants.js.map +1 -1
  152. package/src/utils/generateUUID.d.ts +12 -1
  153. package/src/utils/generateUUID.d.ts.map +1 -1
  154. package/src/utils/generateUUID.js +31 -266
  155. package/src/utils/generateUUID.js.map +2 -2
  156. package/src/utils/props-utils.d.ts +3 -2
  157. package/src/utils/props-utils.d.ts.map +1 -1
  158. package/src/utils/props-utils.js +13 -24
  159. package/src/utils/props-utils.js.map +2 -2
  160. package/src/utils/runGuarded.d.ts +27 -0
  161. package/src/utils/runGuarded.d.ts.map +1 -0
  162. package/src/utils/runGuarded.js +11 -0
  163. package/src/utils/runGuarded.js.map +7 -0
  164. package/src/utils/toMaybe.d.ts.map +1 -1
  165. package/src/utils/toMaybe.js.map +1 -1
  166. package/src/utils/toNamespace.d.ts.map +1 -1
  167. package/src/utils/toNamespace.js.map +1 -1
  168. package/src/utils/toUrlString.d.ts +12 -0
  169. package/src/utils/toUrlString.d.ts.map +1 -1
  170. package/src/utils/toUrlString.js.map +2 -2
  171. package/src/utils/waitForMessageOfType.d.ts +16 -1
  172. package/src/utils/waitForMessageOfType.d.ts.map +1 -1
  173. package/src/utils/waitForMessageOfType.js +28 -3
  174. package/src/utils/waitForMessageOfType.js.map +2 -2
  175. package/src/view/ComponentChanges.d.ts +91 -1
  176. package/src/view/ComponentChanges.d.ts.map +1 -1
  177. package/src/view/ComponentChanges.js +253 -69
  178. package/src/view/ComponentChanges.js.map +2 -2
  179. package/src/view/ComponentContext.d.ts +239 -7
  180. package/src/view/ComponentContext.d.ts.map +1 -1
  181. package/src/view/ComponentContext.js +648 -115
  182. package/src/view/ComponentContext.js.map +2 -2
  183. package/src/view/ComponentMemory.d.ts +3 -3
  184. package/src/view/ComponentMemory.d.ts.map +1 -1
  185. package/src/view/ComponentMemory.js +3 -1
  186. package/src/view/ComponentMemory.js.map +2 -2
  187. package/src/view/IShadowObjectEnvProxy.d.ts +33 -1
  188. package/src/view/IShadowObjectEnvProxy.d.ts.map +1 -1
  189. package/src/view/LocalShadowObjectEnv.d.ts +2 -2
  190. package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
  191. package/src/view/LocalShadowObjectEnv.js +18 -11
  192. package/src/view/LocalShadowObjectEnv.js.map +2 -2
  193. package/src/view/RemoteWorkerEnv.d.ts +129 -3
  194. package/src/view/RemoteWorkerEnv.d.ts.map +1 -1
  195. package/src/view/RemoteWorkerEnv.js +290 -60
  196. package/src/view/RemoteWorkerEnv.js.map +2 -2
  197. package/src/view/ShadowEnv.d.ts +73 -2
  198. package/src/view/ShadowEnv.d.ts.map +1 -1
  199. package/src/view/ShadowEnv.js +301 -64
  200. package/src/view/ShadowEnv.js.map +2 -2
  201. package/src/view/ViewComponent.d.ts +93 -8
  202. package/src/view/ViewComponent.d.ts.map +1 -1
  203. package/src/view/ViewComponent.js +148 -28
  204. package/src/view/ViewComponent.js.map +2 -2
  205. package/src/view/cloneChangeTrail.js.map +2 -2
  206. package/src/worker/MessageRouter.d.ts +14 -0
  207. package/src/worker/MessageRouter.d.ts.map +1 -1
  208. package/src/worker/MessageRouter.js +80 -18
  209. package/src/worker/MessageRouter.js.map +2 -2
  210. package/src/worker/WorkerRuntime.d.ts +22 -1
  211. package/src/worker/WorkerRuntime.d.ts.map +1 -1
  212. package/src/worker/WorkerRuntime.js +60 -8
  213. package/src/worker/WorkerRuntime.js.map +2 -2
@@ -0,0 +1,20 @@
1
+ class MicrotaskGate {
2
+ #scheduled = false;
3
+ #run;
4
+ constructor(run) {
5
+ this.#run = run;
6
+ }
7
+ /** Ask for the action. */
8
+ schedule() {
9
+ if (this.#scheduled) return;
10
+ this.#scheduled = true;
11
+ queueMicrotask(() => {
12
+ this.#scheduled = false;
13
+ this.#run();
14
+ });
15
+ }
16
+ }
17
+ export {
18
+ MicrotaskGate
19
+ };
20
+ //# sourceMappingURL=MicrotaskGate.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/MicrotaskGate.ts"],
4
+ "sourcesContent": ["/**\n * Runs one action a microtask after it was asked for, however often it is asked for.\n *\n * The flag falls before the action rather than behind it: an action that asks again books a fresh\n * round instead of writing into a flag the line behind it would clear.\n *\n * No batch and no guard: there is one action, so there are no neighbours a failure could cost --\n * what it throws goes where an uncaught microtask goes. A gate that carries entries is\n * `MicrotaskCollector`, a booking that can be called off again is `DeferredTeardown`.\n */\nexport class MicrotaskGate {\n #scheduled = false;\n\n readonly #run: () => void;\n\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Ask for the action. */\n schedule(): void {\n if (this.#scheduled) return;\n this.#scheduled = true;\n\n queueMicrotask(() => {\n this.#scheduled = false;\n this.#run();\n });\n }\n}\n"],
5
+ "mappings": "AAUO,MAAM,cAAc;AAAA,EACzB,aAAa;AAAA,EAEJ;AAAA,EAET,YAAY,KAAiB;AAC3B,SAAK,OAAO;AAAA,EACd;AAAA;AAAA,EAGA,WAAiB;AACf,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa;AAElB,mBAAe,MAAM;AACnB,WAAK,aAAa;AAClB,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AACF;",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/array-utils.ts"],
4
- "sourcesContent": ["/**\n * Add a new item to the array, but only if it does not already exist\n */\nexport function appendTo<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index === -1) {\n array.push(item);\n }\n}\n\n/**\n * Append a new item to the end of the array.\n * If the item exists, remove the previous item first.\n */\nexport function appendToEnd<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index !== -1) {\n array.splice(index, 1);\n }\n array.push(item);\n}\n\nexport function removeFrom<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index !== -1) {\n array.splice(index, 1);\n }\n}"],
4
+ "sourcesContent": ["/**\n * Add a new item to the array, but only if it does not already exist\n */\nexport function appendTo<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index === -1) {\n array.push(item);\n }\n}\n\n/**\n * Append a new item to the end of the array.\n * If the item exists, remove the previous item first.\n */\nexport function appendToEnd<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index !== -1) {\n array.splice(index, 1);\n }\n array.push(item);\n}\n\nexport function removeFrom<T = unknown>(array: T[], item: T) {\n const index = array.indexOf(item);\n if (index !== -1) {\n array.splice(index, 1);\n }\n}\n"],
5
5
  "mappings": "AAGO,SAAS,SAAsB,OAAY,MAAS;AACzD,QAAM,QAAQ,MAAM,QAAQ,IAAI;AAChC,MAAI,UAAU,IAAI;AAChB,UAAM,KAAK,IAAI;AAAA,EACjB;AACF;AAMO,SAAS,YAAyB,OAAY,MAAS;AAC5D,QAAM,QAAQ,MAAM,QAAQ,IAAI;AAChC,MAAI,UAAU,IAAI;AAChB,UAAM,OAAO,OAAO,CAAC;AAAA,EACvB;AACA,QAAM,KAAK,IAAI;AACjB;AAEO,SAAS,WAAwB,OAAY,MAAS;AAC3D,QAAM,QAAQ,MAAM,QAAQ,IAAI;AAChC,MAAI,UAAU,IAAI;AAChB,UAAM,OAAO,OAAO,CAAC;AAAA,EACvB;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,3 +1,9 @@
1
1
  export declare const readNamespaceAttribute: (el: HTMLElement) => import("../types.js").NamespaceType;
2
2
  export declare const readBooleanAttribute: (el: HTMLElement, name: string) => boolean;
3
+ /**
4
+ * The attribute read as a number, or `undefined` where the element does not carry it.
5
+ * `Number()` does the reading, so a value that is not a number reads as `NaN` while an empty
6
+ * or blank one reads as `0` — whoever asks decides what either of those means.
7
+ */
8
+ export declare const readNumberAttribute: (el: HTMLElement, name: string) => number | undefined;
3
9
  //# sourceMappingURL=attr-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attr-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/attr-utils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,GAAI,IAAI,WAAW,wCAA0C,CAAC;AAEjG,eAAO,MAAM,oBAAoB,GAAI,IAAI,WAAW,EAAE,MAAM,MAAM,YAMjE,CAAC"}
1
+ {"version":3,"file":"attr-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/attr-utils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,OAAQ,WAAW,wCAAuD,CAAC;AAE9G,eAAO,MAAM,oBAAoB,OAAQ,WAAW,QAAQ,MAAM,YAMjE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,OAAQ,WAAW,QAAQ,MAAM,KAAG,MAAM,GAAG,SACV,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { ATTR_NS } from "../elements/constants.js";
2
2
  import { TRUTHY_VALUES } from "./constants.js";
3
3
  import { toNamespace } from "./toNamespace.js";
4
- const readNamespaceAttribute = (el) => toNamespace(el.getAttribute(ATTR_NS));
4
+ const readNamespaceAttribute = (el) => toNamespace(el.getAttribute(ATTR_NS) ?? void 0);
5
5
  const readBooleanAttribute = (el, name) => {
6
6
  if (el.hasAttribute(name)) {
7
7
  const val = el.getAttribute(name)?.trim()?.toLowerCase() || "1";
@@ -9,8 +9,10 @@ const readBooleanAttribute = (el, name) => {
9
9
  }
10
10
  return false;
11
11
  };
12
+ const readNumberAttribute = (el, name) => el.hasAttribute(name) ? Number(el.getAttribute(name)) : void 0;
12
13
  export {
13
14
  readBooleanAttribute,
14
- readNamespaceAttribute
15
+ readNamespaceAttribute,
16
+ readNumberAttribute
15
17
  };
16
18
  //# sourceMappingURL=attr-utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/attr-utils.ts"],
4
- "sourcesContent": ["import {ATTR_NS} from '../elements/constants.js';\nimport {TRUTHY_VALUES} from './constants.js';\nimport {toNamespace} from './toNamespace.js';\n\nexport const readNamespaceAttribute = (el: HTMLElement) => toNamespace(el.getAttribute(ATTR_NS));\n\nexport const readBooleanAttribute = (el: HTMLElement, name: string) => {\n if (el.hasAttribute(name)) {\n const val = el.getAttribute(name)?.trim()?.toLowerCase() || '1';\n return TRUTHY_VALUES.has(val);\n }\n return false;\n};"],
5
- "mappings": "AAAA,SAAQ,eAAc;AACtB,SAAQ,qBAAoB;AAC5B,SAAQ,mBAAkB;AAEnB,MAAM,yBAAyB,CAAC,OAAoB,YAAY,GAAG,aAAa,OAAO,CAAC;AAExF,MAAM,uBAAuB,CAAC,IAAiB,SAAiB;AACrE,MAAI,GAAG,aAAa,IAAI,GAAG;AACzB,UAAM,MAAM,GAAG,aAAa,IAAI,GAAG,KAAK,GAAG,YAAY,KAAK;AAC5D,WAAO,cAAc,IAAI,GAAG;AAAA,EAC9B;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import {ATTR_NS} from '../elements/constants.js';\nimport {TRUTHY_VALUES} from './constants.js';\nimport {toNamespace} from './toNamespace.js';\n\nexport const readNamespaceAttribute = (el: HTMLElement) => toNamespace(el.getAttribute(ATTR_NS) ?? undefined);\n\nexport const readBooleanAttribute = (el: HTMLElement, name: string) => {\n if (el.hasAttribute(name)) {\n const val = el.getAttribute(name)?.trim()?.toLowerCase() || '1';\n return TRUTHY_VALUES.has(val);\n }\n return false;\n};\n\n/**\n * The attribute read as a number, or `undefined` where the element does not carry it.\n * `Number()` does the reading, so a value that is not a number reads as `NaN` while an empty\n * or blank one reads as `0` \u2014 whoever asks decides what either of those means.\n */\nexport const readNumberAttribute = (el: HTMLElement, name: string): number | undefined =>\n el.hasAttribute(name) ? Number(el.getAttribute(name)) : undefined;\n"],
5
+ "mappings": "AAAA,SAAQ,eAAc;AACtB,SAAQ,qBAAoB;AAC5B,SAAQ,mBAAkB;AAEnB,MAAM,yBAAyB,CAAC,OAAoB,YAAY,GAAG,aAAa,OAAO,KAAK,MAAS;AAErG,MAAM,uBAAuB,CAAC,IAAiB,SAAiB;AACrE,MAAI,GAAG,aAAa,IAAI,GAAG;AACzB,UAAM,MAAM,GAAG,aAAa,IAAI,GAAG,KAAK,GAAG,YAAY,KAAK;AAC5D,WAAO,cAAc,IAAI,GAAG;AAAA,EAC9B;AACA,SAAO;AACT;AAOO,MAAM,sBAAsB,CAAC,IAAiB,SACnD,GAAG,aAAa,IAAI,IAAI,OAAO,GAAG,aAAa,IAAI,CAAC,IAAI;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/constants.ts"],
4
- "sourcesContent": ["export const TRUTHY_VALUES = new Set(['on', 'true', 'yes', 'local', '1']);"],
4
+ "sourcesContent": ["export const TRUTHY_VALUES = new Set(['on', 'true', 'yes', 'local', '1']);\n"],
5
5
  "mappings": "AAAO,MAAM,gBAAgB,oBAAI,IAAI,CAAC,MAAM,QAAQ,OAAO,SAAS,GAAG,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,13 @@
1
- export declare const generateUUID: () => string;
1
+ /**
2
+ * A version-4 uuid in the canonical 8-4-4-4-12 form, from the best source this realm offers.
3
+ *
4
+ * Three of them, in order. `crypto.randomUUID()` is bound to a secure context and is out of
5
+ * reach whenever the page is served over plain http -- a LAN address during development is
6
+ * the usual way to meet that. `crypto.getRandomValues()` carries no such restriction and is
7
+ * the same cryptographic generator, so the step down to it costs four lines of formatting and
8
+ * nothing else. Only a realm with no Web Crypto API at all reaches `Math.random()`, and that
9
+ * one says so on the console, once: the uuids stay unique enough to name an entity, and they
10
+ * stop being unguessable.
11
+ */
12
+ export declare const generateUUID: () => `${string}-${string}-${string}-${string}-${string}`;
2
13
  //# sourceMappingURL=generateUUID.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateUUID.d.ts","sourceRoot":"","sources":["../../../src/utils/generateUUID.ts"],"names":[],"mappings":"AAsSA,eAAO,MAAM,YAAY,cAA8D,CAAC"}
1
+ {"version":3,"file":"generateUUID.d.ts","sourceRoot":"","sources":["../../../src/utils/generateUUID.ts"],"names":[],"mappings":"AAqDA;;;;;;;;;;GAUG;AAKH,eAAO,MAAM,YAAY,2DAYxB,CAAC"}
@@ -1,270 +1,35 @@
1
- const _lut = [
2
- "00",
3
- "01",
4
- "02",
5
- "03",
6
- "04",
7
- "05",
8
- "06",
9
- "07",
10
- "08",
11
- "09",
12
- "0a",
13
- "0b",
14
- "0c",
15
- "0d",
16
- "0e",
17
- "0f",
18
- "10",
19
- "11",
20
- "12",
21
- "13",
22
- "14",
23
- "15",
24
- "16",
25
- "17",
26
- "18",
27
- "19",
28
- "1a",
29
- "1b",
30
- "1c",
31
- "1d",
32
- "1e",
33
- "1f",
34
- "20",
35
- "21",
36
- "22",
37
- "23",
38
- "24",
39
- "25",
40
- "26",
41
- "27",
42
- "28",
43
- "29",
44
- "2a",
45
- "2b",
46
- "2c",
47
- "2d",
48
- "2e",
49
- "2f",
50
- "30",
51
- "31",
52
- "32",
53
- "33",
54
- "34",
55
- "35",
56
- "36",
57
- "37",
58
- "38",
59
- "39",
60
- "3a",
61
- "3b",
62
- "3c",
63
- "3d",
64
- "3e",
65
- "3f",
66
- "40",
67
- "41",
68
- "42",
69
- "43",
70
- "44",
71
- "45",
72
- "46",
73
- "47",
74
- "48",
75
- "49",
76
- "4a",
77
- "4b",
78
- "4c",
79
- "4d",
80
- "4e",
81
- "4f",
82
- "50",
83
- "51",
84
- "52",
85
- "53",
86
- "54",
87
- "55",
88
- "56",
89
- "57",
90
- "58",
91
- "59",
92
- "5a",
93
- "5b",
94
- "5c",
95
- "5d",
96
- "5e",
97
- "5f",
98
- "60",
99
- "61",
100
- "62",
101
- "63",
102
- "64",
103
- "65",
104
- "66",
105
- "67",
106
- "68",
107
- "69",
108
- "6a",
109
- "6b",
110
- "6c",
111
- "6d",
112
- "6e",
113
- "6f",
114
- "70",
115
- "71",
116
- "72",
117
- "73",
118
- "74",
119
- "75",
120
- "76",
121
- "77",
122
- "78",
123
- "79",
124
- "7a",
125
- "7b",
126
- "7c",
127
- "7d",
128
- "7e",
129
- "7f",
130
- "80",
131
- "81",
132
- "82",
133
- "83",
134
- "84",
135
- "85",
136
- "86",
137
- "87",
138
- "88",
139
- "89",
140
- "8a",
141
- "8b",
142
- "8c",
143
- "8d",
144
- "8e",
145
- "8f",
146
- "90",
147
- "91",
148
- "92",
149
- "93",
150
- "94",
151
- "95",
152
- "96",
153
- "97",
154
- "98",
155
- "99",
156
- "9a",
157
- "9b",
158
- "9c",
159
- "9d",
160
- "9e",
161
- "9f",
162
- "a0",
163
- "a1",
164
- "a2",
165
- "a3",
166
- "a4",
167
- "a5",
168
- "a6",
169
- "a7",
170
- "a8",
171
- "a9",
172
- "aa",
173
- "ab",
174
- "ac",
175
- "ad",
176
- "ae",
177
- "af",
178
- "b0",
179
- "b1",
180
- "b2",
181
- "b3",
182
- "b4",
183
- "b5",
184
- "b6",
185
- "b7",
186
- "b8",
187
- "b9",
188
- "ba",
189
- "bb",
190
- "bc",
191
- "bd",
192
- "be",
193
- "bf",
194
- "c0",
195
- "c1",
196
- "c2",
197
- "c3",
198
- "c4",
199
- "c5",
200
- "c6",
201
- "c7",
202
- "c8",
203
- "c9",
204
- "ca",
205
- "cb",
206
- "cc",
207
- "cd",
208
- "ce",
209
- "cf",
210
- "d0",
211
- "d1",
212
- "d2",
213
- "d3",
214
- "d4",
215
- "d5",
216
- "d6",
217
- "d7",
218
- "d8",
219
- "d9",
220
- "da",
221
- "db",
222
- "dc",
223
- "dd",
224
- "de",
225
- "df",
226
- "e0",
227
- "e1",
228
- "e2",
229
- "e3",
230
- "e4",
231
- "e5",
232
- "e6",
233
- "e7",
234
- "e8",
235
- "e9",
236
- "ea",
237
- "eb",
238
- "ec",
239
- "ed",
240
- "ee",
241
- "ef",
242
- "f0",
243
- "f1",
244
- "f2",
245
- "f3",
246
- "f4",
247
- "f5",
248
- "f6",
249
- "f7",
250
- "f8",
251
- "f9",
252
- "fa",
253
- "fb",
254
- "fc",
255
- "fd",
256
- "fe",
257
- "ff"
258
- ];
259
- const _generateUUID = () => {
260
- const d0 = Math.random() * 4294967295 | 0;
261
- const d1 = Math.random() * 4294967295 | 0;
262
- const d2 = Math.random() * 4294967295 | 0;
263
- const d3 = Math.random() * 4294967295 | 0;
264
- const uuid = _lut[d0 & 255] + _lut[d0 >> 8 & 255] + _lut[d0 >> 16 & 255] + _lut[d0 >> 24 & 255] + "-" + _lut[d1 & 255] + _lut[d1 >> 8 & 255] + "-" + _lut[d1 >> 16 & 15 | 64] + _lut[d1 >> 24 & 255] + "-" + _lut[d2 & 63 | 128] + _lut[d2 >> 8 & 255] + "-" + _lut[d2 >> 16 & 255] + _lut[d2 >> 24 & 255] + _lut[d3 & 255] + _lut[d3 >> 8 & 255] + _lut[d3 >> 16 & 255] + _lut[d3 >> 24 & 255];
265
- return uuid.toLowerCase();
1
+ import { ConsoleLogger } from "./ConsoleLogger.js";
2
+ const UUID_BYTE_COUNT = 16;
3
+ const toUuidV4 = (bytes) => {
4
+ bytes[6] = bytes[6] & 15 | 64;
5
+ bytes[8] = bytes[8] & 63 | 128;
6
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
7
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
8
+ };
9
+ let mathRandomAnnounced = false;
10
+ const mathRandomBytes = () => {
11
+ if (!mathRandomAnnounced) {
12
+ mathRandomAnnounced = true;
13
+ new ConsoleLogger("generateUUID").error(
14
+ "no Web Crypto API in this realm: entity uuids come from Math.random() and are not unguessable"
15
+ );
16
+ }
17
+ const bytes = new Uint8Array(UUID_BYTE_COUNT);
18
+ for (let i = 0; i < bytes.length; i++) {
19
+ bytes[i] = Math.random() * 256 | 0;
20
+ }
21
+ return bytes;
22
+ };
23
+ const generateUUID = () => {
24
+ const webCrypto = globalThis.crypto;
25
+ if (typeof webCrypto?.randomUUID === "function") {
26
+ return webCrypto.randomUUID();
27
+ }
28
+ if (typeof webCrypto?.getRandomValues === "function") {
29
+ return toUuidV4(webCrypto.getRandomValues(new Uint8Array(UUID_BYTE_COUNT)));
30
+ }
31
+ return toUuidV4(mathRandomBytes());
266
32
  };
267
- const generateUUID = () => globalThis?.crypto?.randomUUID?.() ?? _generateUUID();
268
33
  export {
269
34
  generateUUID
270
35
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/generateUUID.ts"],
4
- "sourcesContent": ["// https://github.com/mrdoob/three.js/blob/master/src/math/MathUtils.js\n\n// prettier-ignore\nconst _lut = [\n '00',\n '01',\n '02',\n '03',\n '04',\n '05',\n '06',\n '07',\n '08',\n '09',\n '0a',\n '0b',\n '0c',\n '0d',\n '0e',\n '0f',\n '10',\n '11',\n '12',\n '13',\n '14',\n '15',\n '16',\n '17',\n '18',\n '19',\n '1a',\n '1b',\n '1c',\n '1d',\n '1e',\n '1f',\n '20',\n '21',\n '22',\n '23',\n '24',\n '25',\n '26',\n '27',\n '28',\n '29',\n '2a',\n '2b',\n '2c',\n '2d',\n '2e',\n '2f',\n '30',\n '31',\n '32',\n '33',\n '34',\n '35',\n '36',\n '37',\n '38',\n '39',\n '3a',\n '3b',\n '3c',\n '3d',\n '3e',\n '3f',\n '40',\n '41',\n '42',\n '43',\n '44',\n '45',\n '46',\n '47',\n '48',\n '49',\n '4a',\n '4b',\n '4c',\n '4d',\n '4e',\n '4f',\n '50',\n '51',\n '52',\n '53',\n '54',\n '55',\n '56',\n '57',\n '58',\n '59',\n '5a',\n '5b',\n '5c',\n '5d',\n '5e',\n '5f',\n '60',\n '61',\n '62',\n '63',\n '64',\n '65',\n '66',\n '67',\n '68',\n '69',\n '6a',\n '6b',\n '6c',\n '6d',\n '6e',\n '6f',\n '70',\n '71',\n '72',\n '73',\n '74',\n '75',\n '76',\n '77',\n '78',\n '79',\n '7a',\n '7b',\n '7c',\n '7d',\n '7e',\n '7f',\n '80',\n '81',\n '82',\n '83',\n '84',\n '85',\n '86',\n '87',\n '88',\n '89',\n '8a',\n '8b',\n '8c',\n '8d',\n '8e',\n '8f',\n '90',\n '91',\n '92',\n '93',\n '94',\n '95',\n '96',\n '97',\n '98',\n '99',\n '9a',\n '9b',\n '9c',\n '9d',\n '9e',\n '9f',\n 'a0',\n 'a1',\n 'a2',\n 'a3',\n 'a4',\n 'a5',\n 'a6',\n 'a7',\n 'a8',\n 'a9',\n 'aa',\n 'ab',\n 'ac',\n 'ad',\n 'ae',\n 'af',\n 'b0',\n 'b1',\n 'b2',\n 'b3',\n 'b4',\n 'b5',\n 'b6',\n 'b7',\n 'b8',\n 'b9',\n 'ba',\n 'bb',\n 'bc',\n 'bd',\n 'be',\n 'bf',\n 'c0',\n 'c1',\n 'c2',\n 'c3',\n 'c4',\n 'c5',\n 'c6',\n 'c7',\n 'c8',\n 'c9',\n 'ca',\n 'cb',\n 'cc',\n 'cd',\n 'ce',\n 'cf',\n 'd0',\n 'd1',\n 'd2',\n 'd3',\n 'd4',\n 'd5',\n 'd6',\n 'd7',\n 'd8',\n 'd9',\n 'da',\n 'db',\n 'dc',\n 'dd',\n 'de',\n 'df',\n 'e0',\n 'e1',\n 'e2',\n 'e3',\n 'e4',\n 'e5',\n 'e6',\n 'e7',\n 'e8',\n 'e9',\n 'ea',\n 'eb',\n 'ec',\n 'ed',\n 'ee',\n 'ef',\n 'f0',\n 'f1',\n 'f2',\n 'f3',\n 'f4',\n 'f5',\n 'f6',\n 'f7',\n 'f8',\n 'f9',\n 'fa',\n 'fb',\n 'fc',\n 'fd',\n 'fe',\n 'ff',\n];\n\nconst _generateUUID = () => {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136\n const d0 = (Math.random() * 0xffffffff) | 0;\n const d1 = (Math.random() * 0xffffffff) | 0;\n const d2 = (Math.random() * 0xffffffff) | 0;\n const d3 = (Math.random() * 0xffffffff) | 0;\n const uuid =\n _lut[d0 & 0xff] +\n _lut[(d0 >> 8) & 0xff] +\n _lut[(d0 >> 16) & 0xff] +\n _lut[(d0 >> 24) & 0xff] +\n '-' +\n _lut[d1 & 0xff] +\n _lut[(d1 >> 8) & 0xff] +\n '-' +\n _lut[((d1 >> 16) & 0x0f) | 0x40] +\n _lut[(d1 >> 24) & 0xff] +\n '-' +\n _lut[(d2 & 0x3f) | 0x80] +\n _lut[(d2 >> 8) & 0xff] +\n '-' +\n _lut[(d2 >> 16) & 0xff] +\n _lut[(d2 >> 24) & 0xff] +\n _lut[d3 & 0xff] +\n _lut[(d3 >> 8) & 0xff] +\n _lut[(d3 >> 16) & 0xff] +\n _lut[(d3 >> 24) & 0xff];\n\n // .toLowerCase() here flattens concatenated strings to save heap memory space.\n return uuid.toLowerCase();\n};\n\nexport const generateUUID = () => globalThis?.crypto?.randomUUID?.() ?? _generateUUID();"],
5
- "mappings": "AAGA,MAAM,OAAO;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,gBAAgB,MAAM;AAE1B,QAAM,KAAM,KAAK,OAAO,IAAI,aAAc;AAC1C,QAAM,KAAM,KAAK,OAAO,IAAI,aAAc;AAC1C,QAAM,KAAM,KAAK,OAAO,IAAI,aAAc;AAC1C,QAAM,KAAM,KAAK,OAAO,IAAI,aAAc;AAC1C,QAAM,OACJ,KAAK,KAAK,GAAI,IACd,KAAM,MAAM,IAAK,GAAI,IACrB,KAAM,MAAM,KAAM,GAAI,IACtB,KAAM,MAAM,KAAM,GAAI,IACtB,MACA,KAAK,KAAK,GAAI,IACd,KAAM,MAAM,IAAK,GAAI,IACrB,MACA,KAAO,MAAM,KAAM,KAAQ,EAAI,IAC/B,KAAM,MAAM,KAAM,GAAI,IACtB,MACA,KAAM,KAAK,KAAQ,GAAI,IACvB,KAAM,MAAM,IAAK,GAAI,IACrB,MACA,KAAM,MAAM,KAAM,GAAI,IACtB,KAAM,MAAM,KAAM,GAAI,IACtB,KAAK,KAAK,GAAI,IACd,KAAM,MAAM,IAAK,GAAI,IACrB,KAAM,MAAM,KAAM,GAAI,IACtB,KAAM,MAAM,KAAM,GAAI;AAGxB,SAAO,KAAK,YAAY;AAC1B;AAEO,MAAM,eAAe,MAAM,YAAY,QAAQ,aAAa,KAAK,cAAc;",
4
+ "sourcesContent": ["import {ConsoleLogger} from './ConsoleLogger.js';\n\n// A uuid here names one Entity and nothing else: it is not a credential, it is not a\n// capability, and it never leaves the process that made it. That is what makes the last of\n// the three sources below tolerable at all, and why it is loud rather than forbidden.\n\nconst UUID_BYTE_COUNT = 16;\n\n// Named after `crypto.randomUUID()`'s own return type instead of spelling out the template\n// literal a second time: the two stay in lockstep by construction, not by copy-paste.\ntype UuidV4 = ReturnType<Crypto['randomUUID']>;\n\n/**\n * Stamps the version and variant bits into 16 random bytes and writes them out in the\n * canonical 8-4-4-4-12 form. The bytes are written to in place, so the caller hands over an\n * array it does not keep.\n *\n * RFC 4122 \u00A74.4: version 4 goes into the high nibble of byte 6, the variant `10xx` into the\n * two high bits of byte 8.\n */\nconst toUuidV4 = (bytes: Uint8Array): UuidV4 => {\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}` as UuidV4;\n};\n\nlet mathRandomAnnounced = false;\n\nconst mathRandomBytes = (): Uint8Array => {\n if (!mathRandomAnnounced) {\n mathRandomAnnounced = true;\n // Once per realm, not once per uuid: an application that makes thousands of them would\n // bury its console, and what is reported is a property of the realm, not of the call.\n //\n // Through `error` and not `warn`: `logger.error` always prints, where `logger.warn` is\n // gated behind `isWarn`, which is off outside `localhost`. Which source a realm offers is\n // a property of the host the application is served from, so this line has to arrive there\n // -- a loopback host is the one place where it does not matter.\n new ConsoleLogger('generateUUID').error(\n 'no Web Crypto API in this realm: entity uuids come from Math.random() and are not unguessable',\n );\n }\n\n const bytes = new Uint8Array(UUID_BYTE_COUNT);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = (Math.random() * 256) | 0;\n }\n return bytes;\n};\n\n/**\n * A version-4 uuid in the canonical 8-4-4-4-12 form, from the best source this realm offers.\n *\n * Three of them, in order. `crypto.randomUUID()` is bound to a secure context and is out of\n * reach whenever the page is served over plain http -- a LAN address during development is\n * the usual way to meet that. `crypto.getRandomValues()` carries no such restriction and is\n * the same cryptographic generator, so the step down to it costs four lines of formatting and\n * nothing else. Only a realm with no Web Crypto API at all reaches `Math.random()`, and that\n * one says so on the console, once: the uuids stay unique enough to name an entity, and they\n * stop being unguessable.\n */\n// No explicit return-type annotation here: emitDeclarationOnly then prints the inferred\n// template-literal form of `UuidV4` rather than the alias name, so callers reading the\n// emitted `.d.ts` see the exact shape `crypto.randomUUID()` guarantees, not a reference they\n// would have to look up.\nexport const generateUUID = () => {\n const webCrypto = (globalThis as {crypto?: Crypto}).crypto;\n\n if (typeof webCrypto?.randomUUID === 'function') {\n return webCrypto.randomUUID();\n }\n\n if (typeof webCrypto?.getRandomValues === 'function') {\n return toUuidV4(webCrypto.getRandomValues(new Uint8Array(UUID_BYTE_COUNT)));\n }\n\n return toUuidV4(mathRandomBytes());\n};\n"],
5
+ "mappings": "AAAA,SAAQ,qBAAoB;AAM5B,MAAM,kBAAkB;AAcxB,MAAM,WAAW,CAAC,UAA8B;AAC9C,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAEhC,QAAM,MAAM,MAAM,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAEnF,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAC1G;AAEA,IAAI,sBAAsB;AAE1B,MAAM,kBAAkB,MAAkB;AACxC,MAAI,CAAC,qBAAqB;AACxB,0BAAsB;AAQtB,QAAI,cAAc,cAAc,EAAE;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,WAAW,eAAe;AAC5C,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,CAAC,IAAK,KAAK,OAAO,IAAI,MAAO;AAAA,EACrC;AACA,SAAO;AACT;AAiBO,MAAM,eAAe,MAAM;AAChC,QAAM,YAAa,WAAiC;AAEpD,MAAI,OAAO,WAAW,eAAe,YAAY;AAC/C,WAAO,UAAU,WAAW;AAAA,EAC9B;AAEA,MAAI,OAAO,WAAW,oBAAoB,YAAY;AACpD,WAAO,SAAS,UAAU,gBAAgB,IAAI,WAAW,eAAe,CAAC,CAAC;AAAA,EAC5E;AAEA,SAAO,SAAS,gBAAgB,CAAC;AACnC;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,9 @@
1
1
  import type { ComponentPropertiesType } from '../types.js';
2
- export declare const filterUndefinedProps: (props: ComponentPropertiesType | undefined) => [string, unknown][];
2
+ export declare const filterUndefinedProps: (props: ComponentPropertiesType | undefined) => ([string] | [string, unknown])[] | undefined;
3
3
  /**
4
4
  * Maybe `curProps` will be modified and returned. But it can also return a newly created array. `changes` will never be modified.
5
+ * The result never shares a tuple with `changes` — except when `curProps === changes`, where `changes`, tuples included, comes back as-is.
6
+ * A list the changes empty out comes back as `undefined`, never as an empty array.
5
7
  */
6
8
  export declare const applyPropsChanges: (curProps: ComponentPropertiesType | undefined, changes: ComponentPropertiesType | undefined) => ComponentPropertiesType | undefined;
7
- export declare const propsEqual: (a: ComponentPropertiesType | undefined, b: ComponentPropertiesType | undefined) => boolean;
8
9
  //# sourceMappingURL=props-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"props-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/props-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,oBAAoB,GAAI,OAAO,uBAAuB,GAAG,SAAS,wBAG9E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,uBAAuB,GAAG,SAAS,EAC7C,SAAS,uBAAuB,GAAG,SAAS,KAC3C,uBAAuB,GAAG,SAc5B,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,GAAG,uBAAuB,GAAG,SAAS,EAAE,GAAG,uBAAuB,GAAG,SAAS,YAaxG,CAAC"}
1
+ {"version":3,"file":"props-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/props-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,oBAAoB,UAAW,uBAAuB,GAAG,SAAS,iDAO9E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,aAClB,uBAAuB,GAAG,SAAS,WACpC,uBAAuB,GAAG,SAAS,KAC3C,uBAAuB,GAAG,SAqB5B,CAAC"}
@@ -1,38 +1,27 @@
1
1
  const filterUndefinedProps = (props) => {
2
- if (props === void 0 || props.length === 0) return void 0;
3
- return props.filter((entry) => entry.length === 1 || entry[1] !== void 0);
2
+ if (props === void 0) return void 0;
3
+ const kept = props.filter((entry) => entry.length === 1 || entry[1] !== void 0);
4
+ return kept.length === 0 ? void 0 : kept;
4
5
  };
5
6
  const applyPropsChanges = (curProps, changes) => {
6
7
  if (curProps === changes) return curProps;
7
8
  if (changes === void 0) return curProps;
8
- if (curProps === void 0) return filterUndefinedProps(changes);
9
- for (const [key, value] of changes) {
10
- const entry = curProps.find(([k]) => k === key);
11
- if (entry === void 0) {
12
- curProps.push([key, value]);
9
+ if (curProps === void 0)
10
+ return filterUndefinedProps(changes)?.map((entry) => entry.length === 1 ? [entry[0]] : [entry[0], entry[1]]);
11
+ for (const change of changes) {
12
+ const key = change[0];
13
+ const next = change.length === 1 ? [key] : [key, change[1]];
14
+ const idx = curProps.findIndex(([k]) => k === key);
15
+ if (idx === -1) {
16
+ curProps.push(next);
13
17
  } else {
14
- entry[1] = value;
18
+ curProps[idx] = next;
15
19
  }
16
20
  }
17
21
  return filterUndefinedProps(curProps);
18
22
  };
19
- const propsEqual = (a, b) => {
20
- if (a === b) return true;
21
- a = filterUndefinedProps(a);
22
- b = filterUndefinedProps(b);
23
- if (a === b) return true;
24
- if (a === void 0 || b === void 0) return false;
25
- if (a.length !== b.length) return false;
26
- for (const [aKey, value] of a) {
27
- const bEntry = b.find(([bKey]) => aKey === bKey);
28
- if (bEntry === void 0) return false;
29
- if (bEntry[1] !== value) return false;
30
- }
31
- return true;
32
- };
33
23
  export {
34
24
  applyPropsChanges,
35
- filterUndefinedProps,
36
- propsEqual
25
+ filterUndefinedProps
37
26
  };
38
27
  //# sourceMappingURL=props-utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/utils/props-utils.ts"],
4
- "sourcesContent": ["import type {ComponentPropertiesType} from '../types.js';\n\nexport const filterUndefinedProps = (props: ComponentPropertiesType | undefined) => {\n if (props === undefined || props.length === 0) return undefined;\n return props.filter((entry) => (entry as Array<any>).length === 1 || entry[1] !== undefined);\n};\n\n/**\n * Maybe `curProps` will be modified and returned. But it can also return a newly created array. `changes` will never be modified.\n */\nexport const applyPropsChanges = (\n curProps: ComponentPropertiesType | undefined,\n changes: ComponentPropertiesType | undefined,\n): ComponentPropertiesType | undefined => {\n if (curProps === changes) return curProps;\n if (changes === undefined) return curProps;\n if (curProps === undefined) return filterUndefinedProps(changes);\n\n for (const [key, value] of changes) {\n const entry = curProps.find(([k]) => k === key);\n if (entry === undefined) {\n curProps.push([key, value]);\n } else {\n entry[1] = value;\n }\n }\n return filterUndefinedProps(curProps);\n};\n\nexport const propsEqual = (a: ComponentPropertiesType | undefined, b: ComponentPropertiesType | undefined) => {\n if (a === b) return true;\n a = filterUndefinedProps(a);\n b = filterUndefinedProps(b);\n if (a === b) return true;\n if (a === undefined || b === undefined) return false;\n if (a.length !== b.length) return false;\n for (const [aKey, value] of a) {\n const bEntry = b.find(([bKey]) => aKey === bKey);\n if (bEntry === undefined) return false;\n if (bEntry[1] !== value) return false;\n }\n return true;\n};"],
5
- "mappings": "AAEO,MAAM,uBAAuB,CAAC,UAA+C;AAClF,MAAI,UAAU,UAAa,MAAM,WAAW,EAAG,QAAO;AACtD,SAAO,MAAM,OAAO,CAAC,UAAW,MAAqB,WAAW,KAAK,MAAM,CAAC,MAAM,MAAS;AAC7F;AAKO,MAAM,oBAAoB,CAC/B,UACA,YACwC;AACxC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,YAAY,OAAW,QAAO;AAClC,MAAI,aAAa,OAAW,QAAO,qBAAqB,OAAO;AAE/D,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,UAAM,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,MAAM,GAAG;AAC9C,QAAI,UAAU,QAAW;AACvB,eAAS,KAAK,CAAC,KAAK,KAAK,CAAC;AAAA,IAC5B,OAAO;AACL,YAAM,CAAC,IAAI;AAAA,IACb;AAAA,EACF;AACA,SAAO,qBAAqB,QAAQ;AACtC;AAEO,MAAM,aAAa,CAAC,GAAwC,MAA2C;AAC5G,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,qBAAqB,CAAC;AAC1B,MAAI,qBAAqB,CAAC;AAC1B,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAC/C,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,aAAW,CAAC,MAAM,KAAK,KAAK,GAAG;AAC7B,UAAM,SAAS,EAAE,KAAK,CAAC,CAAC,IAAI,MAAM,SAAS,IAAI;AAC/C,QAAI,WAAW,OAAW,QAAO;AACjC,QAAI,OAAO,CAAC,MAAM,MAAO,QAAO;AAAA,EAClC;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import type {ComponentPropertiesType} from '../types.js';\n\nexport const filterUndefinedProps = (props: ComponentPropertiesType | undefined) => {\n if (props === undefined) return undefined;\n // an entry that names only the key survives the filter: it means \"set, without a value\", while\n // `[key, undefined]` means the value is gone. See ComponentPropertiesType for the whole rule\n const kept = props.filter((entry) => entry.length === 1 || entry[1] !== undefined);\n // \"nothing\" has one form here: whoever gets an array gets one with at least one entry in it\n return kept.length === 0 ? undefined : kept;\n};\n\n/**\n * Maybe `curProps` will be modified and returned. But it can also return a newly created array. `changes` will never be modified.\n * The result never shares a tuple with `changes` \u2014 except when `curProps === changes`, where `changes`, tuples included, comes back as-is.\n * A list the changes empty out comes back as `undefined`, never as an empty array.\n */\nexport const applyPropsChanges = (\n curProps: ComponentPropertiesType | undefined,\n changes: ComponentPropertiesType | undefined,\n): ComponentPropertiesType | undefined => {\n if (curProps === changes) return curProps;\n if (changes === undefined) return curProps;\n // the tuples belong to `changes` \u2014 a change trail that has been handed out is a value, and\n // every entry that stays here is one this function built itself\n if (curProps === undefined)\n return filterUndefinedProps(changes)?.map((entry) => (entry.length === 1 ? [entry[0]] : [entry[0], entry[1]]));\n\n for (const change of changes) {\n const key = change[0];\n // the arity carries the meaning: a one-element entry says \"set, without a value\" and has to\n // stay one element on the way in, so the length decides the shape of the copy\n const next: [string] | [string, unknown] = change.length === 1 ? [key] : [key, change[1]];\n const idx = curProps.findIndex(([k]) => k === key);\n if (idx === -1) {\n curProps.push(next);\n } else {\n curProps[idx] = next;\n }\n }\n return filterUndefinedProps(curProps);\n};\n"],
5
+ "mappings": "AAEO,MAAM,uBAAuB,CAAC,UAA+C;AAClF,MAAI,UAAU,OAAW,QAAO;AAGhC,QAAM,OAAO,MAAM,OAAO,CAAC,UAAU,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM,MAAS;AAEjF,SAAO,KAAK,WAAW,IAAI,SAAY;AACzC;AAOO,MAAM,oBAAoB,CAC/B,UACA,YACwC;AACxC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,YAAY,OAAW,QAAO;AAGlC,MAAI,aAAa;AACf,WAAO,qBAAqB,OAAO,GAAG,IAAI,CAAC,UAAW,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE;AAE/G,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,OAAO,CAAC;AAGpB,UAAM,OAAqC,OAAO,WAAW,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC;AACxF,UAAM,MAAM,SAAS,UAAU,CAAC,CAAC,CAAC,MAAM,MAAM,GAAG;AACjD,QAAI,QAAQ,IAAI;AACd,eAAS,KAAK,IAAI;AAAA,IACpB,OAAO;AACL,eAAS,GAAG,IAAI;AAAA,IAClB;AAAA,EACF;AACA,SAAO,qBAAqB,QAAQ;AACtC;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,27 @@
1
+ import type { ConsoleLogger } from './ConsoleLogger.js';
2
+ /**
3
+ * Runs one teardown step and keeps whatever it throws to itself.
4
+ *
5
+ * The kernel answers a failure on two paths. A path that builds hands its error to the caller and
6
+ * takes back what it had already built, so the caller learns that nothing of its request stands. A
7
+ * path that tears down catches per step, reports it and carries on, because there is no caller left
8
+ * to decide anything and the steps behind the failing one still have to run. This function carries
9
+ * that second promise: a step that fails costs itself and nothing around it.
10
+ *
11
+ * A report always reads `message`, then whatever names the subject of the step, then the error. The
12
+ * error goes last, and this is the one place that decides so -- a caller hands over its identity
13
+ * arguments and never the error itself.
14
+ *
15
+ * `logger.error` sits behind no switch, so these reports stay visible outside localhost, where a
16
+ * failing teardown would otherwise be silent.
17
+ *
18
+ * The behaviour a consumer sees from this is written out in the section "Two error contracts" of
19
+ * `docs/api-reference.md`.
20
+ *
21
+ * @param message names the step that failed, in the tone `<subject> … failed:` or
22
+ * `<subject> could not …:`, and ends on a colon.
23
+ * @param details name what the step worked on, the most specific first -- the display name of a
24
+ * shadow object before the uuid of its entity.
25
+ */
26
+ export declare function runGuarded(logger: ConsoleLogger, run: () => void, message: string, ...details: unknown[]): void;
27
+ //# sourceMappingURL=runGuarded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runGuarded.d.ts","sourceRoot":"","sources":["../../../src/utils/runGuarded.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAM/G"}
@@ -0,0 +1,11 @@
1
+ function runGuarded(logger, run, message, ...details) {
2
+ try {
3
+ run();
4
+ } catch (error) {
5
+ logger.error(message, ...details, error);
6
+ }
7
+ }
8
+ export {
9
+ runGuarded
10
+ };
11
+ //# sourceMappingURL=runGuarded.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/runGuarded.ts"],
4
+ "sourcesContent": ["import type {ConsoleLogger} from './ConsoleLogger.js';\n\n/**\n * Runs one teardown step and keeps whatever it throws to itself.\n *\n * The kernel answers a failure on two paths. A path that builds hands its error to the caller and\n * takes back what it had already built, so the caller learns that nothing of its request stands. A\n * path that tears down catches per step, reports it and carries on, because there is no caller left\n * to decide anything and the steps behind the failing one still have to run. This function carries\n * that second promise: a step that fails costs itself and nothing around it.\n *\n * A report always reads `message`, then whatever names the subject of the step, then the error. The\n * error goes last, and this is the one place that decides so -- a caller hands over its identity\n * arguments and never the error itself.\n *\n * `logger.error` sits behind no switch, so these reports stay visible outside localhost, where a\n * failing teardown would otherwise be silent.\n *\n * The behaviour a consumer sees from this is written out in the section \"Two error contracts\" of\n * `docs/api-reference.md`.\n *\n * @param message names the step that failed, in the tone `<subject> \u2026 failed:` or\n * `<subject> could not \u2026:`, and ends on a colon.\n * @param details name what the step worked on, the most specific first -- the display name of a\n * shadow object before the uuid of its entity.\n */\nexport function runGuarded(logger: ConsoleLogger, run: () => void, message: string, ...details: unknown[]): void {\n try {\n run();\n } catch (error) {\n logger.error(message, ...details, error);\n }\n}\n"],
5
+ "mappings": "AA0BO,SAAS,WAAW,QAAuB,KAAiB,YAAoB,SAA0B;AAC/G,MAAI;AACF,QAAI;AAAA,EACN,SAAS,OAAO;AACd,WAAO,MAAM,SAAS,GAAG,SAAS,KAAK;AAAA,EACzC;AACF;",
6
+ "names": []
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"toMaybe.d.ts","sourceRoot":"","sources":["../../../src/utils/toMaybe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,aAAa,CAAC;AAEvC,eAAO,MAAM,OAAO,GAAI,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,KAAG,KAAK,CAAC,CAAC,CAAuB,CAAC"}
1
+ {"version":3,"file":"toMaybe.d.ts","sourceRoot":"","sources":["../../../src/utils/toMaybe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,aAAa,CAAC;AAEvC,eAAO,MAAM,OAAO,GAAI,CAAC,GAAG,OAAO,SAAS,CAAC,KAAG,KAAK,CAAC,CAAC,CAAuB,CAAC"}