@gyral/core 0.3.0 → 0.3.2

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 (386) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/NOTICE +19 -0
  3. package/README.md +36 -8
  4. package/dist/call.d.ts +32 -0
  5. package/dist/call.js +63 -0
  6. package/dist/call.js.map +1 -0
  7. package/dist/children.d.ts +25 -3
  8. package/dist/children.js +18 -1
  9. package/dist/children.js.map +1 -1
  10. package/dist/cli/gyral-types.d.ts +2 -0
  11. package/dist/cli/gyral-types.js +23 -0
  12. package/dist/cli/gyral-types.js.map +1 -0
  13. package/dist/command.d.ts +54 -12
  14. package/dist/command.js +25 -11
  15. package/dist/command.js.map +1 -1
  16. package/dist/compiler/ast.d.ts +2 -0
  17. package/dist/compiler/ast.js +5 -1
  18. package/dist/compiler/ast.js.map +1 -1
  19. package/dist/compiler/compile.d.ts +5 -2
  20. package/dist/compiler/compile.js +36 -17
  21. package/dist/compiler/compile.js.map +1 -1
  22. package/dist/compiler/component-entries.d.ts +7 -0
  23. package/dist/compiler/component-entries.js +42 -0
  24. package/dist/compiler/component-entries.js.map +1 -0
  25. package/dist/compiler/components.d.ts +4 -0
  26. package/dist/compiler/components.js +190 -0
  27. package/dist/compiler/components.js.map +1 -0
  28. package/dist/compiler/facts.d.ts +31 -0
  29. package/dist/compiler/facts.js +285 -0
  30. package/dist/compiler/facts.js.map +1 -0
  31. package/dist/compiler/features.d.ts +34 -0
  32. package/dist/compiler/features.js +158 -0
  33. package/dist/compiler/features.js.map +1 -0
  34. package/dist/compiler/hooks.d.ts +4 -0
  35. package/dist/compiler/hooks.js +144 -89
  36. package/dist/compiler/hooks.js.map +1 -1
  37. package/dist/compiler/loader-source.d.ts +14 -0
  38. package/dist/compiler/loader-source.js +86 -0
  39. package/dist/compiler/loader-source.js.map +1 -0
  40. package/dist/compiler/locate.d.ts +14 -0
  41. package/dist/compiler/locate.js +90 -0
  42. package/dist/compiler/locate.js.map +1 -0
  43. package/dist/compiler/parse5-check.d.ts +1 -1
  44. package/dist/compiler/parse5-check.js +8 -3
  45. package/dist/compiler/parse5-check.js.map +1 -1
  46. package/dist/compiler/prop-schemas.d.ts +4 -0
  47. package/dist/compiler/prop-schemas.js +108 -0
  48. package/dist/compiler/prop-schemas.js.map +1 -0
  49. package/dist/compiler/scan.d.ts +13 -3
  50. package/dist/compiler/scan.js +21 -13
  51. package/dist/compiler/scan.js.map +1 -1
  52. package/dist/compiler/scope.d.ts +8 -0
  53. package/dist/compiler/scope.js +116 -0
  54. package/dist/compiler/scope.js.map +1 -0
  55. package/dist/compiler/tag-map.d.ts +41 -0
  56. package/dist/compiler/tag-map.js +126 -0
  57. package/dist/compiler/tag-map.js.map +1 -0
  58. package/dist/components-ready.d.ts +7 -0
  59. package/dist/components-ready.js +19 -0
  60. package/dist/components-ready.js.map +1 -0
  61. package/dist/define.d.ts +12 -4
  62. package/dist/define.js +8 -12
  63. package/dist/define.js.map +1 -1
  64. package/dist/devtools-events.d.ts +8 -0
  65. package/dist/devtools-events.js.map +1 -1
  66. package/dist/devtools-off.d.ts +1 -0
  67. package/dist/devtools-off.js +1 -0
  68. package/dist/devtools-off.js.map +1 -1
  69. package/dist/devtools.d.ts +3 -0
  70. package/dist/devtools.js +14 -0
  71. package/dist/devtools.js.map +1 -1
  72. package/dist/drivers-scope.js.map +1 -1
  73. package/dist/element-internals.d.ts +1 -0
  74. package/dist/element-internals.js +11 -0
  75. package/dist/element-internals.js.map +1 -0
  76. package/dist/element-types.d.ts +7 -4
  77. package/dist/element-types.js.map +1 -1
  78. package/dist/element.js +80 -27
  79. package/dist/element.js.map +1 -1
  80. package/dist/error-view.d.ts +10 -0
  81. package/dist/error-view.js +30 -0
  82. package/dist/error-view.js.map +1 -0
  83. package/dist/errors.d.ts +21 -0
  84. package/dist/errors.js +47 -0
  85. package/dist/errors.js.map +1 -0
  86. package/dist/errors.json +289 -0
  87. package/dist/eslint/imports.d.ts +2 -0
  88. package/dist/eslint/imports.js +2 -2
  89. package/dist/eslint/imports.js.map +1 -1
  90. package/dist/eslint/index.d.ts +2 -1
  91. package/dist/eslint/index.js +11 -3
  92. package/dist/eslint/index.js.map +1 -1
  93. package/dist/eslint/template-rule.d.ts +1 -0
  94. package/dist/eslint/template-rule.js +15 -5
  95. package/dist/eslint/template-rule.js.map +1 -1
  96. package/dist/eslint/unused-intent-rule.d.ts +2 -0
  97. package/dist/eslint/unused-intent-rule.js +186 -0
  98. package/dist/eslint/unused-intent-rule.js.map +1 -0
  99. package/dist/features.d.ts +2 -2
  100. package/dist/features.js.map +1 -1
  101. package/dist/focus.d.ts +6 -0
  102. package/dist/focus.js +32 -2
  103. package/dist/focus.js.map +1 -1
  104. package/dist/form-associated.d.ts +46 -0
  105. package/dist/form-associated.js +77 -0
  106. package/dist/form-associated.js.map +1 -0
  107. package/dist/forms.d.ts +42 -30
  108. package/dist/forms.js +85 -41
  109. package/dist/forms.js.map +1 -1
  110. package/dist/frame-lane.d.ts +11 -0
  111. package/dist/frame-lane.js +28 -0
  112. package/dist/frame-lane.js.map +1 -0
  113. package/dist/head.d.ts +61 -0
  114. package/dist/head.js +85 -0
  115. package/dist/head.js.map +1 -0
  116. package/dist/host-model.d.ts +34 -5
  117. package/dist/host-model.js +146 -23
  118. package/dist/host-model.js.map +1 -1
  119. package/dist/hydration-client.js +2 -2
  120. package/dist/hydration-client.js.map +1 -1
  121. package/dist/hydration-loader.d.ts +13 -0
  122. package/dist/hydration-loader.js +58 -0
  123. package/dist/hydration-loader.js.map +1 -0
  124. package/dist/hydration-off.d.ts +8 -0
  125. package/dist/hydration-off.js +25 -0
  126. package/dist/hydration-off.js.map +1 -0
  127. package/dist/hydration.d.ts +0 -12
  128. package/dist/hydration.js +3 -52
  129. package/dist/hydration.js.map +1 -1
  130. package/dist/index.d.ts +21 -24
  131. package/dist/index.js +10 -19
  132. package/dist/index.js.map +1 -1
  133. package/dist/indexeddb-types.d.ts +97 -0
  134. package/dist/indexeddb-types.js +2 -0
  135. package/dist/indexeddb-types.js.map +1 -0
  136. package/dist/indexeddb.d.ts +5 -0
  137. package/dist/indexeddb.js +118 -0
  138. package/dist/indexeddb.js.map +1 -0
  139. package/dist/intent.d.ts +42 -20
  140. package/dist/intent.js +145 -107
  141. package/dist/intent.js.map +1 -1
  142. package/dist/internal/indexeddb-open.d.ts +8 -0
  143. package/dist/internal/indexeddb-open.js +96 -0
  144. package/dist/internal/indexeddb-open.js.map +1 -0
  145. package/dist/internal/indexeddb-transaction.d.ts +4 -0
  146. package/dist/internal/indexeddb-transaction.js +134 -0
  147. package/dist/internal/indexeddb-transaction.js.map +1 -0
  148. package/dist/internal/interpreter.d.ts +12 -4
  149. package/dist/internal/interpreter.js +36 -48
  150. package/dist/internal/interpreter.js.map +1 -1
  151. package/dist/internal/token.d.ts +1 -0
  152. package/dist/internal/token.js +7 -0
  153. package/dist/internal/token.js.map +1 -0
  154. package/dist/internal.d.ts +20 -0
  155. package/dist/internal.js +22 -0
  156. package/dist/internal.js.map +1 -0
  157. package/dist/invoker-fallback-used.d.ts +4 -0
  158. package/dist/invoker-fallback-used.js +10 -0
  159. package/dist/invoker-fallback-used.js.map +1 -0
  160. package/dist/invoker-fallback.d.ts +4 -0
  161. package/dist/invoker-fallback.js +15 -0
  162. package/dist/invoker-fallback.js.map +1 -0
  163. package/dist/light-dom.d.ts +1 -1
  164. package/dist/light-dom.js.map +1 -1
  165. package/dist/prop.d.ts +30 -7
  166. package/dist/prop.js +19 -0
  167. package/dist/prop.js.map +1 -1
  168. package/dist/props.d.ts +8 -3
  169. package/dist/props.js +22 -15
  170. package/dist/props.js.map +1 -1
  171. package/dist/retry.d.ts +15 -0
  172. package/dist/retry.js +48 -0
  173. package/dist/retry.js.map +1 -0
  174. package/dist/scheduler.d.ts +7 -3
  175. package/dist/scheduler.js +38 -56
  176. package/dist/scheduler.js.map +1 -1
  177. package/dist/script-json.d.ts +2 -0
  178. package/dist/script-json.js +13 -0
  179. package/dist/script-json.js.map +1 -0
  180. package/dist/server-component.d.ts +1 -1
  181. package/dist/server-component.js +45 -14
  182. package/dist/server-component.js.map +1 -1
  183. package/dist/server.d.ts +9 -3
  184. package/dist/server.js +12 -3
  185. package/dist/server.js.map +1 -1
  186. package/dist/settled.d.ts +4 -3
  187. package/dist/settled.js +48 -26
  188. package/dist/settled.js.map +1 -1
  189. package/dist/spec-features-used.d.ts +21 -0
  190. package/dist/spec-features-used.js +50 -0
  191. package/dist/spec-features-used.js.map +1 -0
  192. package/dist/spec-features.d.ts +28 -0
  193. package/dist/spec-features.js +42 -0
  194. package/dist/spec-features.js.map +1 -0
  195. package/dist/states.d.ts +3 -5
  196. package/dist/states.js +22 -8
  197. package/dist/states.js.map +1 -1
  198. package/dist/storage.d.ts +69 -0
  199. package/dist/storage.js +158 -0
  200. package/dist/storage.js.map +1 -0
  201. package/dist/store-binding.js +2 -2
  202. package/dist/store-binding.js.map +1 -1
  203. package/dist/store-scope.d.ts +2 -4
  204. package/dist/store-scope.js +6 -16
  205. package/dist/store-scope.js.map +1 -1
  206. package/dist/store.d.ts +2 -6
  207. package/dist/store.js +36 -8
  208. package/dist/store.js.map +1 -1
  209. package/dist/subscription.d.ts +35 -0
  210. package/dist/subscription.js +74 -0
  211. package/dist/subscription.js.map +1 -0
  212. package/dist/subscriptions.d.ts +26 -0
  213. package/dist/subscriptions.js +98 -0
  214. package/dist/subscriptions.js.map +1 -0
  215. package/dist/transitions.d.ts +4 -5
  216. package/dist/transitions.js +10 -4
  217. package/dist/transitions.js.map +1 -1
  218. package/dist/types.d.ts +141 -32
  219. package/dist/types.js.map +1 -1
  220. package/dist/use-dialogs.d.ts +2 -0
  221. package/dist/use-dialogs.js +9 -0
  222. package/dist/use-dialogs.js.map +1 -0
  223. package/dist/use-disposal.d.ts +2 -0
  224. package/dist/use-disposal.js +9 -0
  225. package/dist/use-disposal.js.map +1 -0
  226. package/dist/use-error-view.d.ts +2 -0
  227. package/dist/use-error-view.js +9 -0
  228. package/dist/use-error-view.js.map +1 -0
  229. package/dist/use-errored.d.ts +2 -0
  230. package/dist/use-errored.js +9 -0
  231. package/dist/use-errored.js.map +1 -0
  232. package/dist/use-form-associated.d.ts +2 -0
  233. package/dist/use-form-associated.js +7 -0
  234. package/dist/use-form-associated.js.map +1 -0
  235. package/dist/use-frame-lane.d.ts +2 -0
  236. package/dist/use-frame-lane.js +10 -0
  237. package/dist/use-frame-lane.js.map +1 -0
  238. package/dist/use-invokers.d.ts +2 -0
  239. package/dist/use-invokers.js +10 -0
  240. package/dist/use-invokers.js.map +1 -0
  241. package/dist/use-states.d.ts +2 -0
  242. package/dist/use-states.js +10 -0
  243. package/dist/use-states.js.map +1 -0
  244. package/dist/use-subscriptions.d.ts +2 -0
  245. package/dist/use-subscriptions.js +10 -0
  246. package/dist/use-subscriptions.js.map +1 -0
  247. package/dist/use-transitions.d.ts +2 -0
  248. package/dist/use-transitions.js +10 -0
  249. package/dist/use-transitions.js.map +1 -0
  250. package/dist/view/attributes.d.ts +5 -0
  251. package/dist/view/attributes.js +5 -0
  252. package/dist/view/attributes.js.map +1 -1
  253. package/dist/view/compiled.d.ts +1 -1
  254. package/dist/view/compiled.js +1 -1
  255. package/dist/view/compiled.js.map +1 -1
  256. package/dist/view/index.d.ts +9 -4
  257. package/dist/view/index.js +9 -3
  258. package/dist/view/index.js.map +1 -1
  259. package/dist/view/loc.d.ts +9 -0
  260. package/dist/view/loc.js +50 -0
  261. package/dist/view/loc.js.map +1 -0
  262. package/dist/view/message.d.ts +17 -0
  263. package/dist/view/message.js +40 -0
  264. package/dist/view/message.js.map +1 -0
  265. package/dist/view/messages.d.ts +43 -0
  266. package/dist/view/messages.js +84 -0
  267. package/dist/view/messages.js.map +1 -0
  268. package/dist/view/normalize/check.d.ts +5 -2
  269. package/dist/view/normalize/check.js +6 -3
  270. package/dist/view/normalize/check.js.map +1 -1
  271. package/dist/view/normalize/emit.d.ts +2 -0
  272. package/dist/view/normalize/emit.js +40 -11
  273. package/dist/view/normalize/emit.js.map +1 -1
  274. package/dist/view/normalize/errors.js +1 -1
  275. package/dist/view/normalize/errors.js.map +1 -1
  276. package/dist/view/normalize/id.d.ts +5 -2
  277. package/dist/view/normalize/id.js +9 -2
  278. package/dist/view/normalize/id.js.map +1 -1
  279. package/dist/view/normalize/normalize.d.ts +7 -4
  280. package/dist/view/normalize/normalize.js +15 -9
  281. package/dist/view/normalize/normalize.js.map +1 -1
  282. package/dist/view/normalize/rules.d.ts +9 -0
  283. package/dist/view/normalize/rules.js +35 -5
  284. package/dist/view/normalize/rules.js.map +1 -1
  285. package/dist/view/normalize/svg.d.ts +14 -0
  286. package/dist/view/normalize/svg.js +40 -0
  287. package/dist/view/normalize/svg.js.map +1 -0
  288. package/dist/view/normalize/tokens.d.ts +5 -1
  289. package/dist/view/normalize/tokens.js.map +1 -1
  290. package/dist/view/normalize/tree.d.ts +8 -2
  291. package/dist/view/normalize/tree.js +58 -13
  292. package/dist/view/normalize/tree.js.map +1 -1
  293. package/dist/view/normalize/types.d.ts +24 -4
  294. package/dist/view/normalize/types.js +4 -1
  295. package/dist/view/normalize/types.js.map +1 -1
  296. package/dist/view/normalize/whitespace.js +4 -3
  297. package/dist/view/normalize/whitespace.js.map +1 -1
  298. package/dist/view/prepare-stub.js +2 -2
  299. package/dist/view/prepare-stub.js.map +1 -1
  300. package/dist/view/prepare.d.ts +5 -2
  301. package/dist/view/prepare.js +9 -3
  302. package/dist/view/prepare.js.map +1 -1
  303. package/dist/view/registry.d.ts +15 -0
  304. package/dist/view/registry.js +10 -2
  305. package/dist/view/registry.js.map +1 -1
  306. package/dist/view/render/adopt-attr.js +7 -1
  307. package/dist/view/render/adopt-attr.js.map +1 -1
  308. package/dist/view/render/adopt.js +21 -4
  309. package/dist/view/render/adopt.js.map +1 -1
  310. package/dist/view/render/attr-parts.d.ts +12 -1
  311. package/dist/view/render/attr-parts.js +38 -5
  312. package/dist/view/render/attr-parts.js.map +1 -1
  313. package/dist/view/render/child-part.js +5 -2
  314. package/dist/view/render/child-part.js.map +1 -1
  315. package/dist/view/render/dispose.d.ts +3 -0
  316. package/dist/view/render/dispose.js +76 -0
  317. package/dist/view/render/dispose.js.map +1 -0
  318. package/dist/view/render/hook-part.d.ts +3 -1
  319. package/dist/view/render/hook-part.js +21 -5
  320. package/dist/view/render/hook-part.js.map +1 -1
  321. package/dist/view/render/hook-run.d.ts +2 -0
  322. package/dist/view/render/hook-run.js +72 -0
  323. package/dist/view/render/hook-run.js.map +1 -0
  324. package/dist/view/render/hooks.d.ts +74 -6
  325. package/dist/view/render/hooks.js +79 -17
  326. package/dist/view/render/hooks.js.map +1 -1
  327. package/dist/view/render/hydrate.js +2 -2
  328. package/dist/view/render/hydrate.js.map +1 -1
  329. package/dist/view/render/keyed.d.ts +6 -0
  330. package/dist/view/render/keyed.js +15 -0
  331. package/dist/view/render/keyed.js.map +1 -0
  332. package/dist/view/render/list.d.ts +1 -1
  333. package/dist/view/render/list.js.map +1 -1
  334. package/dist/view/render/mismatch.js +5 -3
  335. package/dist/view/render/mismatch.js.map +1 -1
  336. package/dist/view/render/modal.d.ts +3 -0
  337. package/dist/view/render/modal.js +39 -0
  338. package/dist/view/render/modal.js.map +1 -0
  339. package/dist/view/render/raw.d.ts +4 -1
  340. package/dist/view/render/raw.js +6 -2
  341. package/dist/view/render/raw.js.map +1 -1
  342. package/dist/view/render/render.d.ts +4 -1
  343. package/dist/view/render/render.js +17 -12
  344. package/dist/view/render/render.js.map +1 -1
  345. package/dist/view/render/toggles.d.ts +6 -0
  346. package/dist/view/render/toggles.js +6 -0
  347. package/dist/view/render/toggles.js.map +1 -0
  348. package/dist/view/render/values.d.ts +1 -1
  349. package/dist/view/render/values.js.map +1 -1
  350. package/dist/view/render/warn.d.ts +14 -0
  351. package/dist/view/render/warn.js +45 -0
  352. package/dist/view/render/warn.js.map +1 -1
  353. package/dist/view/server/component.d.ts +6 -3
  354. package/dist/view/server/component.js +29 -7
  355. package/dist/view/server/component.js.map +1 -1
  356. package/dist/view/server/index.d.ts +20 -0
  357. package/dist/view/server/index.js +12 -4
  358. package/dist/view/server/index.js.map +1 -1
  359. package/dist/view/server/tags.d.ts +13 -2
  360. package/dist/view/server/tags.js +13 -2
  361. package/dist/view/server/tags.js.map +1 -1
  362. package/dist/view/server/values.d.ts +2 -0
  363. package/dist/view/server/values.js +8 -0
  364. package/dist/view/server/values.js.map +1 -1
  365. package/dist/view/server/writer.d.ts +9 -4
  366. package/dist/view/server/writer.js +33 -18
  367. package/dist/view/server/writer.js.map +1 -1
  368. package/dist/view/template-element.d.ts +7 -0
  369. package/dist/view/template-element.js +25 -5
  370. package/dist/view/template-element.js.map +1 -1
  371. package/dist/view/template.d.ts +9 -2
  372. package/dist/view/template.js +61 -8
  373. package/dist/view/template.js.map +1 -1
  374. package/dist/view/trusted-html.d.ts +6 -0
  375. package/dist/view/trusted-html.js +34 -0
  376. package/dist/view/trusted-html.js.map +1 -0
  377. package/dist/vite.d.ts +38 -31
  378. package/dist/vite.js +206 -31
  379. package/dist/vite.js.map +1 -1
  380. package/package.json +34 -3
  381. package/dist/hooks/labelled-by.d.ts +0 -13
  382. package/dist/hooks/labelled-by.js +0 -51
  383. package/dist/hooks/labelled-by.js.map +0 -1
  384. package/dist/random.d.ts +0 -13
  385. package/dist/random.js +0 -19
  386. package/dist/random.js.map +0 -1
@@ -0,0 +1,134 @@
1
+ import { databaseError } from './indexeddb-open.js';
2
+ const rangeOf = (range) => {
3
+ if (range === undefined)
4
+ return undefined;
5
+ switch (range._tag) {
6
+ case 'Only':
7
+ return IDBKeyRange.only(range.key);
8
+ case 'Lower':
9
+ return IDBKeyRange.lowerBound(range.key, range.open);
10
+ case 'Upper':
11
+ return IDBKeyRange.upperBound(range.key, range.open);
12
+ case 'Bound':
13
+ return IDBKeyRange.bound(range.lower, range.upper, range.lowerOpen, range.upperOpen);
14
+ }
15
+ };
16
+ /** Queue requests synchronously and resolve only from transaction complete. */
17
+ export function transact(db, operations, signal) {
18
+ return new Promise((resolve, reject) => {
19
+ signal.throwIfAborted();
20
+ const mode = operations.some((op) => op._tag === 'Put' || op._tag === 'Delete')
21
+ ? 'readwrite'
22
+ : 'readonly';
23
+ const tx = db.transaction([...new Set(operations.map((op) => op.store))], mode);
24
+ const state = { ended: false };
25
+ const results = [];
26
+ const releaseRequests = [];
27
+ let failure;
28
+ const cleanup = () => {
29
+ signal.removeEventListener('abort', abort);
30
+ tx.oncomplete = null;
31
+ tx.onabort = null;
32
+ tx.onerror = null;
33
+ for (const release of releaseRequests)
34
+ release();
35
+ };
36
+ const end = (cause) => {
37
+ if (state.ended)
38
+ return;
39
+ state.ended = true;
40
+ cleanup();
41
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- preserve AbortSignal reasons
42
+ reject(cause);
43
+ };
44
+ const stop = () => {
45
+ try {
46
+ tx.abort();
47
+ }
48
+ catch {
49
+ /* A completed transaction cannot be undone. */
50
+ }
51
+ };
52
+ const abort = () => {
53
+ stop();
54
+ end(signal.reason);
55
+ };
56
+ signal.addEventListener('abort', abort, { once: true });
57
+ tx.onerror = (event) => {
58
+ if (event.target instanceof IDBRequest)
59
+ failure = event.target.error;
60
+ };
61
+ tx.onabort = () => {
62
+ end(databaseError(db.name, 'transaction', failure ?? tx.error ?? new Error('Transaction aborted.')));
63
+ };
64
+ tx.oncomplete = () => {
65
+ if (state.ended)
66
+ return;
67
+ state.ended = true;
68
+ cleanup();
69
+ resolve(results);
70
+ };
71
+ try {
72
+ operations.forEach((op, position) => {
73
+ const store = tx.objectStore(op.store);
74
+ if (op._tag === 'Read') {
75
+ const request = store.openCursor(IDBKeyRange.only(op.key));
76
+ releaseRequests.push(() => {
77
+ request.onsuccess = null;
78
+ });
79
+ request.onsuccess = () => {
80
+ const cursor = request.result;
81
+ const value = cursor?.value;
82
+ results[position] = {
83
+ _tag: 'Record',
84
+ store: op.store,
85
+ key: op.key,
86
+ entry: cursor === null ? { found: false } : { found: true, value },
87
+ };
88
+ };
89
+ }
90
+ else if (op._tag === 'Query') {
91
+ const rows = [];
92
+ results[position] = { _tag: 'Records', store: op.store, records: rows };
93
+ const source = op.index === undefined ? store : store.index(op.index);
94
+ const request = source.openCursor(rangeOf(op.range), op.direction);
95
+ releaseRequests.push(() => {
96
+ request.onsuccess = null;
97
+ });
98
+ request.onsuccess = () => {
99
+ const cursor = request.result;
100
+ if (cursor === null)
101
+ return;
102
+ const value = cursor.value;
103
+ rows.push({ key: cursor.primaryKey, value });
104
+ if (rows.length < op.limit)
105
+ cursor.continue();
106
+ };
107
+ }
108
+ else if (op._tag === 'Put') {
109
+ const request = op.key === undefined ? store.put(op.value) : store.put(op.value, op.key);
110
+ releaseRequests.push(() => {
111
+ request.onsuccess = null;
112
+ });
113
+ request.onsuccess = () => {
114
+ results[position] = { _tag: 'Put', store: op.store, key: request.result };
115
+ };
116
+ }
117
+ else {
118
+ const request = store.delete(op.key);
119
+ releaseRequests.push(() => {
120
+ request.onsuccess = null;
121
+ });
122
+ request.onsuccess = () => {
123
+ results[position] = { _tag: 'Deleted', store: op.store, key: op.key };
124
+ };
125
+ }
126
+ });
127
+ }
128
+ catch (cause) {
129
+ stop();
130
+ end(databaseError(db.name, 'transaction', cause));
131
+ }
132
+ });
133
+ }
134
+ //# sourceMappingURL=indexeddb-transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-transaction.js","sourceRoot":"","sources":["../../src/internal/indexeddb-transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n IndexedDBOperation,\n IndexedDBRange,\n IndexedDBResult,\n IndexedDBStores,\n} from '../indexeddb-types.js';\nimport { databaseError } from './indexeddb-open.js';\n\nexport type RawResult = IndexedDBResult<IndexedDBStores>;\nconst rangeOf = (range: IndexedDBRange | undefined): IDBKeyRange | undefined => {\n if (range === undefined) return undefined;\n switch (range._tag) {\n case 'Only':\n return IDBKeyRange.only(range.key);\n case 'Lower':\n return IDBKeyRange.lowerBound(range.key, range.open);\n case 'Upper':\n return IDBKeyRange.upperBound(range.key, range.open);\n case 'Bound':\n return IDBKeyRange.bound(range.lower, range.upper, range.lowerOpen, range.upperOpen);\n }\n};\n\n/** Queue requests synchronously and resolve only from transaction complete. */\nexport function transact(\n db: IDBDatabase,\n operations: readonly IndexedDBOperation<IndexedDBStores>[],\n signal: AbortSignal,\n): Promise<readonly RawResult[]> {\n return new Promise((resolve, reject) => {\n signal.throwIfAborted();\n const mode = operations.some((op) => op._tag === 'Put' || op._tag === 'Delete')\n ? 'readwrite'\n : 'readonly';\n const tx = db.transaction([...new Set(operations.map((op) => op.store))], mode);\n const state = { ended: false };\n const results: RawResult[] = [];\n const releaseRequests: (() => void)[] = [];\n let failure: unknown;\n const cleanup = (): void => {\n signal.removeEventListener('abort', abort);\n tx.oncomplete = null;\n tx.onabort = null;\n tx.onerror = null;\n for (const release of releaseRequests) release();\n };\n const end = (cause: unknown): void => {\n if (state.ended) return;\n state.ended = true;\n cleanup();\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- preserve AbortSignal reasons\n reject(cause);\n };\n const stop = (): void => {\n try {\n tx.abort();\n } catch {\n /* A completed transaction cannot be undone. */\n }\n };\n const abort = (): void => {\n stop();\n end(signal.reason);\n };\n signal.addEventListener('abort', abort, { once: true });\n tx.onerror = (event) => {\n if (event.target instanceof IDBRequest) failure = event.target.error;\n };\n tx.onabort = () => {\n end(\n databaseError(\n db.name,\n 'transaction',\n failure ?? tx.error ?? new Error('Transaction aborted.'),\n ),\n );\n };\n tx.oncomplete = () => {\n if (state.ended) return;\n state.ended = true;\n cleanup();\n resolve(results);\n };\n try {\n operations.forEach((op, position) => {\n const store = tx.objectStore(op.store);\n if (op._tag === 'Read') {\n const request = store.openCursor(IDBKeyRange.only(op.key));\n releaseRequests.push(() => {\n request.onsuccess = null;\n });\n request.onsuccess = () => {\n const cursor = request.result;\n const value: unknown = cursor?.value;\n results[position] = {\n _tag: 'Record',\n store: op.store,\n key: op.key,\n entry: cursor === null ? { found: false } : { found: true, value },\n };\n };\n } else if (op._tag === 'Query') {\n const rows: { key: IDBValidKey; value: unknown }[] = [];\n results[position] = { _tag: 'Records', store: op.store, records: rows };\n const source = op.index === undefined ? store : store.index(op.index);\n const request = source.openCursor(rangeOf(op.range), op.direction);\n releaseRequests.push(() => {\n request.onsuccess = null;\n });\n request.onsuccess = () => {\n const cursor = request.result;\n if (cursor === null) return;\n const value: unknown = cursor.value;\n rows.push({ key: cursor.primaryKey, value });\n if (rows.length < op.limit) cursor.continue();\n };\n } else if (op._tag === 'Put') {\n const request = op.key === undefined ? store.put(op.value) : store.put(op.value, op.key);\n releaseRequests.push(() => {\n request.onsuccess = null;\n });\n request.onsuccess = () => {\n results[position] = { _tag: 'Put', store: op.store, key: request.result };\n };\n } else {\n const request = store.delete(op.key);\n releaseRequests.push(() => {\n request.onsuccess = null;\n });\n request.onsuccess = () => {\n results[position] = { _tag: 'Deleted', store: op.store, key: op.key };\n };\n }\n });\n } catch (cause) {\n stop();\n end(databaseError(db.name, 'transaction', cause));\n }\n });\n}\n"]}
@@ -1,14 +1,22 @@
1
- import type { AnyDriver, Command, DriverOverrides } from '../command.js';
1
+ import type { AnyDriver, Command } from '../command.js';
2
2
  import type { CommandTrace } from '../devtools-events.js';
3
3
  import type { FeatureHost } from '../features.js';
4
4
  /** Runs commands for one connected element. Disposed on disconnect. */
5
5
  export interface Interpreter<M> {
6
6
  readonly run: (cmd: Command<M>) => void;
7
+ /** Aborts the running task of `lane`, if any (subscriptions.ts: a subscription that left). */
8
+ readonly cancel: (lane: string) => void;
7
9
  readonly dispose: () => void;
8
10
  }
9
- export declare function makeInterpreter<M>(resolve: (driver: AnyDriver) => AnyDriver, dispatch: (msg: M) => void, trace?: CommandTrace): Interpreter<M>;
11
+ /**
12
+ * Reports a failure to the owner (ADR 0024): `40` a mapper threw, `41` a driver failed and the
13
+ * command has no `onFailure`, `43` nothing provides a driver token. The owner builds the message
14
+ * and reports it.
15
+ */
16
+ export type CommandFailure = (cause: unknown, code: 40 | 41 | 43, driver: string) => void;
17
+ export declare function makeInterpreter<M>(resolve: (driver: AnyDriver) => AnyDriver, dispatch: (msg: M) => void, trace: CommandTrace | undefined, failed: CommandFailure): Interpreter<M>;
10
18
  /**
11
19
  * A component's interpreter (registered by `command()`, features.ts). Drivers resolve by name:
12
- * el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
20
+ * el.drivers → nearest provider → the command's own (gyral-czi.35; ADR 0006 "Driver tokens").
13
21
  */
14
- export declare const hostInterpreter: <M>(el: FeatureHost, drivers: DriverOverrides | undefined, dispatch: (msg: M) => void, trace: CommandTrace | undefined) => Interpreter<M>;
22
+ export declare const hostInterpreter: <M>(el: FeatureHost, dispatch: (msg: M) => void, trace: CommandTrace | undefined, failed: CommandFailure) => Interpreter<M>;
@@ -1,5 +1,6 @@
1
1
  import { DEVTOOLS_ENABLED } from '#devtools';
2
2
  import { providedDriver } from '../drivers-scope.js';
3
+ import { unprovided } from './token.js';
3
4
  /** Rejects when `signal` aborts. Marked handled so a losing race never reports it. */
4
5
  const aborted = (signal) => {
5
6
  const promise = new Promise((_resolve, reject) => {
@@ -15,52 +16,35 @@ const aborted = (signal) => {
15
16
  promise.catch(() => undefined);
16
17
  return promise;
17
18
  };
18
- /** Waits `ms`, or rejects as soon as `signal` aborts. */
19
- const sleep = (ms, signal) => Promise.race([
20
- new Promise((resolve) => {
21
- const timer = setTimeout(resolve, ms);
22
- signal.addEventListener('abort', () => {
23
- clearTimeout(timer);
24
- }, { once: true });
25
- }),
19
+ /** Runs the driver once; an abort settles it at once, even if the driver ignores the signal. */
20
+ const attempt = (driver, cmd, signal, emit) =>
21
+ // The input type was erased by command(); it was built for this driver's name.
22
+ Promise.race([
23
+ Promise.resolve(driver.run(cmd.input, { signal, emit })),
26
24
  aborted(signal),
27
25
  ]);
28
- /** Delay before retry number `retry` (0-based): fixed, or doubling from `delayMs`. */
29
- const delayFor = (policy, retry) => {
30
- const base = policy.delayMs ?? 0;
31
- return policy.backoff === 'exponential' ? base * 2 ** retry : base;
32
- };
33
- async function attemptWithRetry(driver, cmd, signal, emit) {
34
- const policy = driver.retry;
35
- for (let retry = 0;; retry += 1) {
36
- try {
37
- // The input type was erased by command(); it was built for this driver's name.
38
- const result = Promise.resolve(driver.run(cmd.input, { signal, emit }));
39
- return await Promise.race([result, aborted(signal)]);
40
- }
41
- catch (cause) {
42
- if (signal.aborted || policy === undefined || retry >= policy.times)
43
- throw cause;
44
- await sleep(delayFor(policy, retry), signal);
45
- }
46
- }
47
- }
48
- /** Maps a result to a message and dispatches it; a throwing mapper is logged, not fatal. */
49
- const deliver = (map, dispatch) => {
26
+ /**
27
+ * Maps a result to a message and dispatches it. A throwing mapper is reported (ADR 0024) and
28
+ * sends nothing; the reducer's own failures are the owner's (dispatch reports them).
29
+ */
30
+ const deliver = (map, dispatch, failed, driver) => {
31
+ let msg;
50
32
  try {
51
- const msg = map();
52
- if (msg !== undefined)
53
- dispatch(msg);
33
+ msg = map();
54
34
  }
55
35
  catch (defect) {
56
- console.error('gyral: command mapper threw', defect);
36
+ failed(defect, 40, driver);
37
+ return;
57
38
  }
39
+ if (msg !== undefined)
40
+ dispatch(msg);
58
41
  };
59
- async function execute(driver, cmd, signal, dispatch, report) {
42
+ async function execute(driver, cmd, signal, dispatch, report, failed) {
60
43
  let settled = false;
44
+ const name = driver.name;
61
45
  const emit = (output) => {
62
46
  if (!settled && !signal.aborted)
63
- deliver(() => cmd.onSuccess(output), dispatch);
47
+ deliver(() => cmd.onSuccess(output), dispatch, failed, name);
64
48
  };
65
49
  if (DEVTOOLS_ENABLED && report !== undefined) {
66
50
  signal.addEventListener('abort', () => {
@@ -70,7 +54,7 @@ async function execute(driver, cmd, signal, dispatch, report) {
70
54
  }
71
55
  let output;
72
56
  try {
73
- output = await attemptWithRetry(driver, cmd, signal, emit);
57
+ output = await attempt(driver, cmd, signal, emit);
74
58
  }
75
59
  catch (cause) {
76
60
  if (signal.aborted)
@@ -80,11 +64,11 @@ async function execute(driver, cmd, signal, dispatch, report) {
80
64
  if (DEVTOOLS_ENABLED)
81
65
  report?.('failed', error);
82
66
  if (cmd.onFailure === undefined) {
83
- console.warn(`gyral: unhandled failure from driver "${driver.name}"`, error);
67
+ failed(error, 41, name);
84
68
  return;
85
69
  }
86
70
  const onFailure = cmd.onFailure;
87
- deliver(() => onFailure(error), dispatch);
71
+ deliver(() => onFailure(error), dispatch, failed, name);
88
72
  return;
89
73
  }
90
74
  if (signal.aborted)
@@ -92,9 +76,9 @@ async function execute(driver, cmd, signal, dispatch, report) {
92
76
  settled = true;
93
77
  if (DEVTOOLS_ENABLED)
94
78
  report?.('settled', output);
95
- deliver(() => cmd.onSuccess(output), dispatch);
79
+ deliver(() => cmd.onSuccess(output), dispatch, failed, name);
96
80
  }
97
- export function makeInterpreter(resolve, dispatch, trace) {
81
+ export function makeInterpreter(resolve, dispatch, trace, failed) {
98
82
  const reporter = (driver, lane, policy, input) => trace === undefined
99
83
  ? undefined
100
84
  : (phase, result) => {
@@ -121,7 +105,7 @@ export function makeInterpreter(resolve, dispatch, trace) {
121
105
  if (after !== undefined)
122
106
  await after.done;
123
107
  if (!controller.signal.aborted) {
124
- await execute(driver, cmd, controller.signal, guardedDispatch, report);
108
+ await execute(driver, cmd, controller.signal, guardedDispatch, report, failed);
125
109
  }
126
110
  };
127
111
  task.done = body().finally(() => {
@@ -137,6 +121,10 @@ export function makeInterpreter(resolve, dispatch, trace) {
137
121
  if (!active)
138
122
  return;
139
123
  const driver = resolve(cmd.driver);
124
+ if (driver.run === unprovided) {
125
+ failed(undefined, 43, driver.name);
126
+ return;
127
+ }
140
128
  const lane = cmd.key ?? driver.name;
141
129
  const policy = cmd.concurrency ?? driver.concurrency ?? 'merge';
142
130
  const previous = lanes.get(lane);
@@ -153,6 +141,9 @@ export function makeInterpreter(resolve, dispatch, trace) {
153
141
  inFlight.controller.abort();
154
142
  start(lane, driver, cmd, report, inFlight !== undefined && policy === 'queue' ? inFlight : undefined);
155
143
  };
144
+ const cancel = (lane) => {
145
+ lanes.get(lane)?.controller.abort();
146
+ };
156
147
  const dispose = () => {
157
148
  active = false;
158
149
  for (const task of all)
@@ -160,14 +151,11 @@ export function makeInterpreter(resolve, dispatch, trace) {
160
151
  all.clear();
161
152
  lanes.clear();
162
153
  };
163
- return { run, dispose };
154
+ return { run, cancel, dispose };
164
155
  }
165
156
  /**
166
157
  * A component's interpreter (registered by `command()`, features.ts). Drivers resolve by name:
167
- * el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
158
+ * el.drivers → nearest provider → the command's own (gyral-czi.35; ADR 0006 "Driver tokens").
168
159
  */
169
- export const hostInterpreter = (el, drivers, dispatch, trace) => makeInterpreter((driver) => el.drivers[driver.name] ??
170
- providedDriver(el, driver.name) ??
171
- drivers?.[driver.name] ??
172
- driver, dispatch, trace);
160
+ export const hostInterpreter = (el, dispatch, trace, failed) => makeInterpreter((driver) => el.drivers[driver.name] ?? providedDriver(el, driver.name) ?? driver, dispatch, trace, failed);
173
161
  //# sourceMappingURL=interpreter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../src/internal/interpreter.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEVTOOLS_ENABLED } from '#devtools';\nimport type { AnyDriver, Command, Concurrency, DriverOverrides, RetryPolicy } from '../command.js';\nimport type { CommandPhase, CommandTrace } from '../devtools-events.js';\nimport { providedDriver } from '../drivers-scope.js';\nimport type { FeatureHost } from '../features.js';\n\n// The command interpreter (ADR 0015: hand-written, no runtime dependencies). Each running command is a task with its own AbortController; lanes hold the\n// latest task per key. Interruption is `controller.abort()`, retry schedules are timers\n// that cancel on abort, and `queue` chains on the previous task's promise.\n\n/** Runs commands for one connected element. Disposed on disconnect. */\nexport interface Interpreter<M> {\n readonly run: (cmd: Command<M>) => void;\n readonly dispose: () => void;\n}\n\ninterface Task {\n readonly controller: AbortController;\n done: Promise<void>;\n running: boolean;\n}\n\n/** Reports one command's lifecycle to devtools (ADR 0017); undefined in production. */\ntype Report = ((phase: CommandPhase, result?: unknown) => void) | undefined;\n\n/** Rejects when `signal` aborts. Marked handled so a losing race never reports it. */\nconst aborted = (signal: AbortSignal): Promise<never> => {\n const promise = new Promise<never>((_resolve, reject) => {\n // Callers check `signal.aborted`, never the reason.\n const interrupt = (): void => {\n reject(signal.reason as Error);\n };\n if (signal.aborted) interrupt();\n else signal.addEventListener('abort', interrupt, { once: true });\n });\n promise.catch(() => undefined);\n return promise;\n};\n\n/** Waits `ms`, or rejects as soon as `signal` aborts. */\nconst sleep = (ms: number, signal: AbortSignal): Promise<void> =>\n Promise.race([\n new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n },\n { once: true },\n );\n }),\n aborted(signal),\n ]);\n\n/** Delay before retry number `retry` (0-based): fixed, or doubling from `delayMs`. */\nconst delayFor = (policy: RetryPolicy, retry: number): number => {\n const base = policy.delayMs ?? 0;\n return policy.backoff === 'exponential' ? base * 2 ** retry : base;\n};\n\nasync function attemptWithRetry(\n driver: AnyDriver,\n cmd: Command<unknown>,\n signal: AbortSignal,\n emit: (output: unknown) => void,\n): Promise<unknown> {\n const policy = driver.retry;\n for (let retry = 0; ; retry += 1) {\n try {\n // The input type was erased by command(); it was built for this driver's name.\n const result = Promise.resolve(driver.run(cmd.input as never, { signal, emit }));\n return await Promise.race([result, aborted(signal)]);\n } catch (cause) {\n if (signal.aborted || policy === undefined || retry >= policy.times) throw cause;\n await sleep(delayFor(policy, retry), signal);\n }\n }\n}\n\n/** Maps a result to a message and dispatches it; a throwing mapper is logged, not fatal. */\nconst deliver = <M>(map: () => M | undefined, dispatch: (msg: M) => void): void => {\n try {\n const msg = map();\n if (msg !== undefined) dispatch(msg);\n } catch (defect) {\n console.error('gyral: command mapper threw', defect);\n }\n};\n\nasync function execute<M>(\n driver: AnyDriver,\n cmd: Command<M>,\n signal: AbortSignal,\n dispatch: (msg: M) => void,\n report: Report,\n): Promise<void> {\n let settled = false;\n const emit = (output: unknown): void => {\n if (!settled && !signal.aborted) deliver(() => cmd.onSuccess(output), dispatch);\n };\n if (DEVTOOLS_ENABLED && report !== undefined) {\n signal.addEventListener(\n 'abort',\n () => {\n if (!settled) report('interrupted');\n },\n { once: true },\n );\n }\n let output: unknown;\n try {\n output = await attemptWithRetry(driver, cmd, signal, emit);\n } catch (cause) {\n if (signal.aborted) return; // interrupted: reported by the abort listener\n settled = true;\n const error = driver.toError === undefined ? cause : driver.toError(cause);\n if (DEVTOOLS_ENABLED) report?.('failed', error);\n if (cmd.onFailure === undefined) {\n console.warn(`gyral: unhandled failure from driver \"${driver.name}\"`, error);\n return;\n }\n const onFailure = cmd.onFailure;\n deliver(() => onFailure(error), dispatch);\n return;\n }\n if (signal.aborted) return;\n settled = true;\n if (DEVTOOLS_ENABLED) report?.('settled', output);\n deliver(() => cmd.onSuccess(output), dispatch);\n}\n\nexport function makeInterpreter<M>(\n resolve: (driver: AnyDriver) => AnyDriver,\n dispatch: (msg: M) => void,\n trace?: CommandTrace,\n): Interpreter<M> {\n const reporter = (driver: string, lane: string, policy: Concurrency, input: unknown): Report =>\n trace === undefined\n ? undefined\n : (phase, result) => {\n trace({\n phase,\n driver,\n lane,\n policy,\n input,\n ...(result === undefined ? {} : { result }),\n });\n };\n const lanes = new Map<string, Task>();\n const all = new Set<Task>();\n let active = true;\n const guardedDispatch = (msg: M): void => {\n if (active) dispatch(msg);\n };\n\n const start = (\n lane: string,\n driver: AnyDriver,\n cmd: Command<M>,\n report: Report,\n after?: Task,\n ): void => {\n const controller = new AbortController();\n const task: Task = { controller, running: true, done: Promise.resolve() };\n const body = async (): Promise<void> => {\n if (after !== undefined) await after.done;\n if (!controller.signal.aborted) {\n await execute(driver, cmd, controller.signal, guardedDispatch, report);\n }\n };\n task.done = body().finally(() => {\n task.running = false;\n all.delete(task);\n if (lanes.get(lane) === task) lanes.delete(lane);\n });\n lanes.set(lane, task);\n all.add(task);\n };\n\n const run = (cmd: Command<M>): void => {\n if (!active) return;\n const driver = resolve(cmd.driver);\n const lane = cmd.key ?? driver.name;\n const policy = cmd.concurrency ?? driver.concurrency ?? 'merge';\n const previous = lanes.get(lane);\n const inFlight = previous?.running === true ? previous : undefined;\n const report = DEVTOOLS_ENABLED ? reporter(driver.name, lane, policy, cmd.input) : undefined;\n if (inFlight !== undefined && policy === 'exhaust') {\n if (DEVTOOLS_ENABLED) report?.('dropped');\n return;\n }\n if (DEVTOOLS_ENABLED) report?.('issued');\n if (inFlight !== undefined && policy === 'switch') inFlight.controller.abort();\n start(\n lane,\n driver,\n cmd,\n report,\n inFlight !== undefined && policy === 'queue' ? inFlight : undefined,\n );\n };\n\n const dispose = (): void => {\n active = false;\n for (const task of all) task.controller.abort();\n all.clear();\n lanes.clear();\n };\n\n return { run, dispose };\n}\n\n/**\n * A component's interpreter (registered by `command()`, features.ts). Drivers resolve by name:\n * el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).\n */\nexport const hostInterpreter = <M>(\n el: FeatureHost,\n drivers: DriverOverrides | undefined,\n dispatch: (msg: M) => void,\n trace: CommandTrace | undefined,\n): Interpreter<M> =>\n makeInterpreter(\n (driver) =>\n el.drivers[driver.name] ??\n providedDriver(el, driver.name) ??\n drivers?.[driver.name] ??\n driver,\n dispatch,\n trace,\n );\n"]}
1
+ {"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../src/internal/interpreter.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEVTOOLS_ENABLED } from '#devtools';\nimport type { AnyDriver, Command, Concurrency } from '../command.js';\nimport type { CommandPhase, CommandTrace } from '../devtools-events.js';\nimport { providedDriver } from '../drivers-scope.js';\nimport type { FeatureHost } from '../features.js';\nimport { unprovided } from './token.js';\n\n// The command interpreter (ADR 0015: hand-written, no runtime dependencies). Each running command is a task with its own AbortController; lanes hold the\n// latest task per key. Interruption is `controller.abort()`,\n// and `queue` chains on the previous task's promise. A driver runs once: retries are a driver\n// wrapper (retry.ts, ADR 0022).\n\n/** Runs commands for one connected element. Disposed on disconnect. */\nexport interface Interpreter<M> {\n readonly run: (cmd: Command<M>) => void;\n /** Aborts the running task of `lane`, if any (subscriptions.ts: a subscription that left). */\n readonly cancel: (lane: string) => void;\n readonly dispose: () => void;\n}\n\ninterface Task {\n readonly controller: AbortController;\n done: Promise<void>;\n running: boolean;\n}\n\n/** Reports one command's lifecycle to devtools (ADR 0017); undefined in production. */\ntype Report = ((phase: CommandPhase, result?: unknown) => void) | undefined;\n\n/**\n * Reports a failure to the owner (ADR 0024): `40` a mapper threw, `41` a driver failed and the\n * command has no `onFailure`, `43` nothing provides a driver token. The owner builds the message\n * and reports it.\n */\nexport type CommandFailure = (cause: unknown, code: 40 | 41 | 43, driver: string) => void;\n\n/** Rejects when `signal` aborts. Marked handled so a losing race never reports it. */\nconst aborted = (signal: AbortSignal): Promise<never> => {\n const promise = new Promise<never>((_resolve, reject) => {\n // Callers check `signal.aborted`, never the reason.\n const interrupt = (): void => {\n reject(signal.reason as Error);\n };\n if (signal.aborted) interrupt();\n else signal.addEventListener('abort', interrupt, { once: true });\n });\n promise.catch(() => undefined);\n return promise;\n};\n\n/** Runs the driver once; an abort settles it at once, even if the driver ignores the signal. */\nconst attempt = (\n driver: AnyDriver,\n cmd: Command<unknown>,\n signal: AbortSignal,\n emit: (output: unknown) => void,\n): Promise<unknown> =>\n // The input type was erased by command(); it was built for this driver's name.\n Promise.race([\n Promise.resolve(driver.run(cmd.input as never, { signal, emit })),\n aborted(signal),\n ]);\n\n/**\n * Maps a result to a message and dispatches it. A throwing mapper is reported (ADR 0024) and\n * sends nothing; the reducer's own failures are the owner's (dispatch reports them).\n */\nconst deliver = <M>(\n map: () => M | undefined,\n dispatch: (msg: M) => void,\n failed: CommandFailure,\n driver: string,\n): void => {\n let msg: M | undefined;\n try {\n msg = map();\n } catch (defect) {\n failed(defect, 40, driver);\n return;\n }\n if (msg !== undefined) dispatch(msg);\n};\n\nasync function execute<M>(\n driver: AnyDriver,\n cmd: Command<M>,\n signal: AbortSignal,\n dispatch: (msg: M) => void,\n report: Report,\n failed: CommandFailure,\n): Promise<void> {\n let settled = false;\n const name = driver.name;\n const emit = (output: unknown): void => {\n if (!settled && !signal.aborted) deliver(() => cmd.onSuccess(output), dispatch, failed, name);\n };\n if (DEVTOOLS_ENABLED && report !== undefined) {\n signal.addEventListener(\n 'abort',\n () => {\n if (!settled) report('interrupted');\n },\n { once: true },\n );\n }\n let output: unknown;\n try {\n output = await attempt(driver, cmd, signal, emit);\n } catch (cause) {\n if (signal.aborted) return; // interrupted: reported by the abort listener\n settled = true;\n const error = driver.toError === undefined ? cause : driver.toError(cause);\n if (DEVTOOLS_ENABLED) report?.('failed', error);\n if (cmd.onFailure === undefined) {\n failed(error, 41, name);\n return;\n }\n const onFailure = cmd.onFailure;\n deliver(() => onFailure(error), dispatch, failed, name);\n return;\n }\n if (signal.aborted) return;\n settled = true;\n if (DEVTOOLS_ENABLED) report?.('settled', output);\n deliver(() => cmd.onSuccess(output), dispatch, failed, name);\n}\n\nexport function makeInterpreter<M>(\n resolve: (driver: AnyDriver) => AnyDriver,\n dispatch: (msg: M) => void,\n trace: CommandTrace | undefined,\n failed: CommandFailure,\n): Interpreter<M> {\n const reporter = (driver: string, lane: string, policy: Concurrency, input: unknown): Report =>\n trace === undefined\n ? undefined\n : (phase, result) => {\n trace({\n phase,\n driver,\n lane,\n policy,\n input,\n ...(result === undefined ? {} : { result }),\n });\n };\n const lanes = new Map<string, Task>();\n const all = new Set<Task>();\n let active = true;\n const guardedDispatch = (msg: M): void => {\n if (active) dispatch(msg);\n };\n\n const start = (\n lane: string,\n driver: AnyDriver,\n cmd: Command<M>,\n report: Report,\n after?: Task,\n ): void => {\n const controller = new AbortController();\n const task: Task = { controller, running: true, done: Promise.resolve() };\n const body = async (): Promise<void> => {\n if (after !== undefined) await after.done;\n if (!controller.signal.aborted) {\n await execute(driver, cmd, controller.signal, guardedDispatch, report, failed);\n }\n };\n task.done = body().finally(() => {\n task.running = false;\n all.delete(task);\n if (lanes.get(lane) === task) lanes.delete(lane);\n });\n lanes.set(lane, task);\n all.add(task);\n };\n\n const run = (cmd: Command<M>): void => {\n if (!active) return;\n const driver = resolve(cmd.driver);\n if (driver.run === unprovided) {\n failed(undefined, 43, driver.name);\n return;\n }\n const lane = cmd.key ?? driver.name;\n const policy = cmd.concurrency ?? driver.concurrency ?? 'merge';\n const previous = lanes.get(lane);\n const inFlight = previous?.running === true ? previous : undefined;\n const report = DEVTOOLS_ENABLED ? reporter(driver.name, lane, policy, cmd.input) : undefined;\n if (inFlight !== undefined && policy === 'exhaust') {\n if (DEVTOOLS_ENABLED) report?.('dropped');\n return;\n }\n if (DEVTOOLS_ENABLED) report?.('issued');\n if (inFlight !== undefined && policy === 'switch') inFlight.controller.abort();\n start(\n lane,\n driver,\n cmd,\n report,\n inFlight !== undefined && policy === 'queue' ? inFlight : undefined,\n );\n };\n\n const cancel = (lane: string): void => {\n lanes.get(lane)?.controller.abort();\n };\n\n const dispose = (): void => {\n active = false;\n for (const task of all) task.controller.abort();\n all.clear();\n lanes.clear();\n };\n\n return { run, cancel, dispose };\n}\n\n/**\n * A component's interpreter (registered by `command()`, features.ts). Drivers resolve by name:\n * el.drivers → nearest provider → the command's own (gyral-czi.35; ADR 0006 \"Driver tokens\").\n */\nexport const hostInterpreter = <M>(\n el: FeatureHost,\n dispatch: (msg: M) => void,\n trace: CommandTrace | undefined,\n failed: CommandFailure,\n): Interpreter<M> =>\n makeInterpreter(\n (driver) => el.drivers[driver.name] ?? providedDriver(el, driver.name) ?? driver,\n dispatch,\n trace,\n failed,\n );\n"]}
@@ -0,0 +1 @@
1
+ export declare function unprovided(): never;
@@ -0,0 +1,7 @@
1
+ // The `run` of a driver token (defineDriver('name'), ADR 0006 "Driver tokens"). The interpreter
2
+ // recognises it and reports G0043 instead of running it; called directly, it throws.
3
+ import { DEV } from '#view-dev';
4
+ export function unprovided() {
5
+ throw new Error(DEV ? 'gyral: this driver is a token; provide an implementation by name' : '');
6
+ }
7
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/internal/token.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,qFAAqF;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,kEAAkE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACjG,CAAC","sourcesContent":["// The `run` of a driver token (defineDriver('name'), ADR 0006 \"Driver tokens\"). The interpreter\n// recognises it and reports G0043 instead of running it; called directly, it throws.\nimport { DEV } from '#view-dev';\n\nexport function unprovided(): never {\n throw new Error(DEV ? 'gyral: this driver is a token; provide an implementation by name' : '');\n}\n"]}
@@ -0,0 +1,20 @@
1
+ export { STORE_SEND } from './store.js';
2
+ export type { StoreSendInput } from './store.js';
3
+ export { scriptSafeJson } from './script-json.js';
4
+ export { STORE_SEED_ATTRIBUTE } from './store-scope.js';
5
+ export { warnJsonHazard } from './json-safety.js';
6
+ export { intentRejectedSchema, isSecretField } from './forms.js';
7
+ export { runInit } from './init.js';
8
+ export { ISLAND_ATTRIBUTE } from './islands.js';
9
+ export { DEVTOOLS_ENABLED as devtoolsEnabled, devLiveComponents as devtoolsLiveComponents, } from '#devtools';
10
+ export { HEAD_ATTRIBUTE, headEntries } from './head.js';
11
+ export type { HeadEntry } from './head.js';
12
+ export { emit } from './children.js';
13
+ export { invokersSupported } from './invokers.js';
14
+ export { resetDocumentStores, STORES_ELEMENT } from './store-scope.js';
15
+ export { DRIVERS_ELEMENT } from './drivers-scope.js';
16
+ export { jsonHazard } from './json-safety.js';
17
+ export { LIGHT_ATTRIBUTE } from './light-dom.js';
18
+ export { HydrationMismatch } from './view/index.js';
19
+ export { DEVTOOLS_GLOBAL } from './devtools-events.js';
20
+ export type { CommandPhase, CommandTraceEvent, DevComponentRef, DevEvent, DevtoolsHook, } from './devtools-events.js';
@@ -0,0 +1,22 @@
1
+ // `@gyral/core/internal`: what Gyral's own packages (@gyral/router, @gyral/ssr, @gyral/testing,
2
+ // @gyral/http, @gyral/devtools) share with core. INTERNAL: not part of Gyral's public API and
3
+ // not covered by semver; any release may change or remove these. Apps import from `@gyral/core`
4
+ // (docs/references/public-api-0.3.1.md).
5
+ export { STORE_SEND } from './store.js';
6
+ export { scriptSafeJson } from './script-json.js';
7
+ export { STORE_SEED_ATTRIBUTE } from './store-scope.js';
8
+ export { warnJsonHazard } from './json-safety.js';
9
+ export { intentRejectedSchema, isSecretField } from './forms.js';
10
+ export { runInit } from './init.js';
11
+ export { ISLAND_ATTRIBUTE } from './islands.js';
12
+ export { DEVTOOLS_ENABLED as devtoolsEnabled, devLiveComponents as devtoolsLiveComponents, } from '#devtools';
13
+ export { HEAD_ATTRIBUTE, headEntries } from './head.js';
14
+ export { emit } from './children.js';
15
+ export { invokersSupported } from './invokers.js';
16
+ export { resetDocumentStores, STORES_ELEMENT } from './store-scope.js';
17
+ export { DRIVERS_ELEMENT } from './drivers-scope.js';
18
+ export { jsonHazard } from './json-safety.js';
19
+ export { LIGHT_ATTRIBUTE } from './light-dom.js';
20
+ export { HydrationMismatch } from './view/index.js';
21
+ export { DEVTOOLS_GLOBAL } from './devtools-events.js';
22
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,gGAAgG;AAChG,yCAAyC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACL,gBAAgB,IAAI,eAAe,EACnC,iBAAiB,IAAI,sBAAsB,GAC5C,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["// `@gyral/core/internal`: what Gyral's own packages (@gyral/router, @gyral/ssr, @gyral/testing,\n// @gyral/http, @gyral/devtools) share with core. INTERNAL: not part of Gyral's public API and\n// not covered by semver; any release may change or remove these. Apps import from `@gyral/core`\n// (docs/references/public-api-0.3.1.md).\nexport { STORE_SEND } from './store.js';\nexport type { StoreSendInput } from './store.js';\nexport { scriptSafeJson } from './script-json.js';\nexport { STORE_SEED_ATTRIBUTE } from './store-scope.js';\nexport { warnJsonHazard } from './json-safety.js';\nexport { intentRejectedSchema, isSecretField } from './forms.js';\nexport { runInit } from './init.js';\nexport { ISLAND_ATTRIBUTE } from './islands.js';\nexport {\n DEVTOOLS_ENABLED as devtoolsEnabled,\n devLiveComponents as devtoolsLiveComponents,\n} from '#devtools';\nexport { HEAD_ATTRIBUTE, headEntries } from './head.js';\nexport type { HeadEntry } from './head.js';\nexport { emit } from './children.js';\nexport { invokersSupported } from './invokers.js';\nexport { resetDocumentStores, STORES_ELEMENT } from './store-scope.js';\nexport { DRIVERS_ELEMENT } from './drivers-scope.js';\nexport { jsonHazard } from './json-safety.js';\nexport { LIGHT_ATTRIBUTE } from './light-dom.js';\nexport { HydrationMismatch } from './view/index.js';\nexport { DEVTOOLS_GLOBAL } from './devtools-events.js';\nexport type {\n CommandPhase,\n CommandTraceEvent,\n DevComponentRef,\n DevEvent,\n DevtoolsHook,\n} from './devtools-events.js';\n"]}
@@ -0,0 +1,4 @@
1
+ /** Loads the fallback for `root`, when the build registered it. */
2
+ export declare const loadInvokerShim: (root: Node) => void;
3
+ /** Turns the fallback on (use-invokers.ts). */
4
+ export declare const useInvokerShim: (load: (root: Node) => void) => void;
@@ -0,0 +1,10 @@
1
+ let loader;
2
+ /** Loads the fallback for `root`, when the build registered it. */
3
+ export const loadInvokerShim = ((root) => {
4
+ loader?.(root);
5
+ });
6
+ /** Turns the fallback on (use-invokers.ts). */
7
+ export const useInvokerShim = ((load) => {
8
+ loader = load;
9
+ });
10
+ //# sourceMappingURL=invoker-fallback-used.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoker-fallback-used.js","sourceRoot":"","sources":["../src/invoker-fallback-used.ts"],"names":[],"mappings":"AAQA,IAAI,MAA0C,CAAC;AAE/C,mEAAmE;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAU,EAAQ,EAAE;IACnD,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC,CAA2C,CAAC;AAE7C,+CAA+C;AAC/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAA0B,EAAQ,EAAE;IAClE,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC,CAA0C,CAAC","sourcesContent":["// `#invoker-fallback` in production client-only builds (gyral-c5d.11, view/05-element.md\n// \"Intent events\"): the fallback's loader (invoker-fallback.ts and its import()) arrives only\n// through `useInvokerShim`, called by use-invokers.ts, which the preset's client-only plugin\n// adds to the build when a module may make a root listen for `command` (compiler/features.ts).\n// Without it the module isn't in the build's graph at all, so neither is the shim's chunk or,\n// with no other import(), Vite's preload helper. Development resolves invoker-fallback.ts.\nimport type * as Fallback from './invoker-fallback.js';\n\nlet loader: ((root: Node) => void) | undefined;\n\n/** Loads the fallback for `root`, when the build registered it. */\nexport const loadInvokerShim = ((root: Node): void => {\n loader?.(root);\n}) satisfies typeof Fallback.loadInvokerShim;\n\n/** Turns the fallback on (use-invokers.ts). */\nexport const useInvokerShim = ((load: (root: Node) => void): void => {\n loader = load;\n}) satisfies typeof Fallback.useInvokerShim;\n"]}
@@ -0,0 +1,4 @@
1
+ /** Loads the fallback for `root` (once per root; the shim module loads once). */
2
+ export declare function loadInvokerShim(root: Node): void;
3
+ /** Registration (use-invokers.ts) is for client-only builds; here the fallback is always on. */
4
+ export declare const useInvokerShim: (load: (root: Node) => void) => void;
@@ -0,0 +1,15 @@
1
+ // Loading the invoker-command fallback (invokers-shim.ts, ADR 0003 tier 3), core's
2
+ // `#invoker-fallback`: a root that listens for `command` intents in a browser without
3
+ // `CommandEvent` loads it with import() (intent.ts); settled() waits. Production client-only
4
+ // builds resolve `#invoker-fallback` to invoker-fallback-used.ts, which reaches this module only
5
+ // when the build saw command intents (use-invokers.ts, gyral-c5d.11).
6
+ import { hold } from './scheduler.js';
7
+ /** Loads the fallback for `root` (once per root; the shim module loads once). */
8
+ export function loadInvokerShim(root) {
9
+ hold(import('./invokers-shim.js').then((shim) => {
10
+ shim.shimInvokers(root);
11
+ }, reportError));
12
+ }
13
+ /** Registration (use-invokers.ts) is for client-only builds; here the fallback is always on. */
14
+ export const useInvokerShim = () => undefined;
15
+ //# sourceMappingURL=invoker-fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoker-fallback.js","sourceRoot":"","sources":["../src/invoker-fallback.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,sFAAsF;AACtF,6FAA6F;AAC7F,iGAAiG;AACjG,sEAAsE;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,IAAI,CACF,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EAAE,WAAW,CAAC,CAChB,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAyC,GAAG,EAAE,CAAC,SAAS,CAAC","sourcesContent":["// Loading the invoker-command fallback (invokers-shim.ts, ADR 0003 tier 3), core's\n// `#invoker-fallback`: a root that listens for `command` intents in a browser without\n// `CommandEvent` loads it with import() (intent.ts); settled() waits. Production client-only\n// builds resolve `#invoker-fallback` to invoker-fallback-used.ts, which reaches this module only\n// when the build saw command intents (use-invokers.ts, gyral-c5d.11).\nimport { hold } from './scheduler.js';\n\n/** Loads the fallback for `root` (once per root; the shim module loads once). */\nexport function loadInvokerShim(root: Node): void {\n hold(\n import('./invokers-shim.js').then((shim) => {\n shim.shimInvokers(root);\n }, reportError),\n );\n}\n\n/** Registration (use-invokers.ts) is for client-only builds; here the fallback is always on. */\nexport const useInvokerShim: (load: (root: Node) => void) => void = () => undefined;\n"]}
@@ -1,5 +1,5 @@
1
1
  interface SpecLike {
2
- readonly shadow?: boolean;
2
+ readonly shadow?: unknown;
3
3
  }
4
4
  export declare const isLight: (spec: SpecLike) => boolean;
5
5
  /** Is this class a light-DOM Gyral component (`shadow: false`)? */
@@ -1 +1 @@
1
- {"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sDAAsD;AAMtD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;AAE1E,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAI,IAA4C,EAAE,IAAI,CAAC;IACjE,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC","sourcesContent":["// Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view\n// as the host's own children, styled by document CSS.\n\ninterface SpecLike {\n readonly shadow?: boolean;\n}\n\nexport const isLight = (spec: SpecLike): boolean => spec.shadow === false;\n\n/** Is this class a light-DOM Gyral component (`shadow: false`)? */\nexport function isLightComponent(ctor: unknown): boolean {\n const spec = (ctor as { readonly spec?: SpecLike } | null)?.spec;\n return spec !== undefined && isLight(spec);\n}\n\n/**\n * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md\n * \"Components\"), so a parent's hydration walk leaves a light child's content alone (view/07).\n */\nexport const LIGHT_ATTRIBUTE = 'data-gyral-light';\n"]}
1
+ {"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sDAAsD;AAMtD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;AAE1E,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAI,IAA4C,EAAE,IAAI,CAAC;IACjE,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC","sourcesContent":["// Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view\n// as the host's own children, styled by document CSS.\n\ninterface SpecLike {\n readonly shadow?: unknown;\n}\n\nexport const isLight = (spec: SpecLike): boolean => spec.shadow === false;\n\n/** Is this class a light-DOM Gyral component (`shadow: false`)? */\nexport function isLightComponent(ctor: unknown): boolean {\n const spec = (ctor as { readonly spec?: SpecLike } | null)?.spec;\n return spec !== undefined && isLight(spec);\n}\n\n/**\n * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md\n * \"Components\"), so a parent's hydration walk leaves a light child's content alone (view/07).\n */\nexport const LIGHT_ATTRIBUTE = 'data-gyral-light';\n"]}
package/dist/prop.d.ts CHANGED
@@ -6,12 +6,20 @@ export interface Prop<T> {
6
6
  readonly kind: PropKind;
7
7
  /** The attribute name, `false` for property only, `undefined` for the kebab-case default. */
8
8
  readonly attribute: string | false | undefined;
9
- /** Refines (string/number/boolean) or defines (json/value) the accepted values. */
10
- readonly schema: StandardSchemaV1 | undefined;
9
+ /**
10
+ * Refines (string/number/boolean) or defines (json/value) the accepted values: a Standard
11
+ * Schema, or for json/value a type guard (props.ts `checkValue` tells them apart).
12
+ */
13
+ readonly schema: StandardSchemaV1 | PropGuard<unknown> | undefined;
11
14
  /** A missing value is a bug: warned once per instance at first render. */
12
15
  readonly required: boolean;
13
16
  /** Used whenever the element's value is missing (`boolean` props default to `false`). */
14
17
  readonly default?: unknown;
18
+ /**
19
+ * When a new value counts as unchanged (no re-render, no `PropsChanged`): `Object.is`, the
20
+ * same JSON for `prop.json`, or the `equals` option of `prop.json`/`prop.value`.
21
+ */
22
+ readonly equals: (a: unknown, b: unknown) => boolean;
15
23
  /** Type-only: the value components see. Never set. */
16
24
  readonly [OUTPUT]?: () => T;
17
25
  }
@@ -24,7 +32,11 @@ interface Common {
24
32
  readonly attribute?: string | false;
25
33
  }
26
34
  type Schema<O> = StandardSchemaV1<unknown, O>;
27
- type Out<S extends StandardSchemaV1> = StandardSchemaV1.InferOutput<S>;
35
+ /** A plain type guard, accepted by `prop.value` and `prop.json` in place of a schema. */
36
+ export type PropGuard<T> = (value: unknown) => value is T;
37
+ /** What `prop.value` and `prop.json` accept: a Standard Schema or a type guard. */
38
+ type Check = StandardSchemaV1 | PropGuard<unknown>;
39
+ type Out<S extends Check> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> : S extends (value: unknown) => value is infer T ? T : never;
28
40
  interface Required {
29
41
  readonly required: true;
30
42
  readonly default?: undefined;
@@ -44,9 +56,13 @@ interface Scalar<B> {
44
56
  <O extends B = B>(opts: Refined<O> & (Required | Defaulted<NoInfer<O>>)): Prop<O>;
45
57
  <O extends B = B>(opts?: Refined<O> & Optional): Prop<O | undefined>;
46
58
  }
59
+ /** `equals` for `prop.json`/`prop.value`: the old and new value (`undefined` when unset). */
60
+ interface Equals<T> {
61
+ readonly equals?: (a: T | undefined, b: T | undefined) => boolean;
62
+ }
47
63
  interface WithSchema {
48
- <S extends StandardSchemaV1>(schema: S, opts: Common & (Required | Defaulted<NoInfer<Out<S>>>)): Prop<Out<S>>;
49
- <S extends StandardSchemaV1>(schema: S, opts?: Common & Optional): Prop<Out<S> | undefined>;
64
+ <S extends Check>(schema: S, opts: Common & Equals<NoInfer<Out<S>>> & (Required | Defaulted<NoInfer<Out<S>>>)): Prop<Out<S>>;
65
+ <S extends Check>(schema: S, opts?: Common & Equals<NoInfer<Out<S>>> & Optional): Prop<Out<S> | undefined>;
50
66
  }
51
67
  /** The prop builders. */
52
68
  export declare const prop: {
@@ -58,9 +74,16 @@ export declare const prop: {
58
74
  readonly boolean: <O extends boolean = boolean>(opts?: Refined<O> & {
59
75
  readonly default?: NoInfer<O>;
60
76
  }) => Prop<O>;
61
- /** Attribute parsed with `JSON.parse`, then the schema. */
77
+ /**
78
+ * Attribute parsed with `JSON.parse`, then the schema (or type guard). Compared by value: a
79
+ * new but equal object (a fresh `.prop=${{…}}` each render) changes nothing.
80
+ */
62
81
  readonly json: WithSchema;
63
- /** Property only: no attribute. Validated in development. */
82
+ /**
83
+ * Property only: no attribute. Validated in development by the schema (or type guard), and
84
+ * the object set is kept as is (production skips the check). Compared with `Object.is`
85
+ * unless `equals` is given.
86
+ */
64
87
  readonly value: WithSchema;
65
88
  };
66
89
  export {};