sigmx 0.1.0 → 0.2.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 (308) hide show
  1. package/README.md +54 -43
  2. package/dist/cli.js +3 -1
  3. package/dist/cli.js.map +2 -2
  4. package/dist/kernel/compile.d.ts +8 -9
  5. package/dist/kernel/compile.js +102 -67
  6. package/dist/kernel/compile.js.map +2 -2
  7. package/dist/kernel/contracts.d.ts +12 -13
  8. package/dist/kernel/index.d.ts +11 -12
  9. package/dist/kernel/index.js +14 -12
  10. package/dist/kernel/index.js.map +3 -3
  11. package/dist/kernel/precompile.d.ts +8 -12
  12. package/dist/kernel/precompile.js +33 -76
  13. package/dist/kernel/precompile.js.map +2 -2
  14. package/dist/kernel/precompiled.d.ts +7 -4
  15. package/dist/kernel/precompiled.js +5 -5
  16. package/dist/kernel/precompiled.js.map +2 -2
  17. package/dist/kernel/reactive.d.ts +13 -11
  18. package/dist/kernel/reactive.js +96 -71
  19. package/dist/kernel/reactive.js.map +3 -3
  20. package/dist/kernel/runtime.js +85 -63
  21. package/dist/kernel/runtime.js.map +3 -3
  22. package/dist/kernel/scan.d.ts +2 -11
  23. package/dist/kernel/scan.js +26 -9
  24. package/dist/kernel/scan.js.map +2 -2
  25. package/dist/kernel/state.d.ts +5 -8
  26. package/dist/kernel/state.js +114 -76
  27. package/dist/kernel/state.js.map +2 -2
  28. package/dist/kernel/strict-csp.d.ts +0 -5
  29. package/dist/kernel/strict-csp.js +2 -2
  30. package/dist/kernel/strict-csp.js.map +2 -2
  31. package/dist/lib/casing.d.ts +4 -1
  32. package/dist/lib/casing.js +8 -1
  33. package/dist/lib/casing.js.map +2 -2
  34. package/dist/lib/objects.d.ts +5 -4
  35. package/dist/lib/objects.js +13 -5
  36. package/dist/lib/objects.js.map +2 -2
  37. package/dist/lib/schedule.d.ts +3 -5
  38. package/dist/lib/schedule.js +12 -10
  39. package/dist/lib/schedule.js.map +2 -2
  40. package/dist/lib/sse.d.ts +10 -1
  41. package/dist/lib/sse.js +32 -28
  42. package/dist/lib/sse.js.map +2 -2
  43. package/dist/plugins/def.d.ts +5 -0
  44. package/dist/plugins/def.js +22 -0
  45. package/dist/plugins/def.js.map +7 -0
  46. package/dist/plugins/directives/attribute-sync.js +8 -12
  47. package/dist/plugins/directives/attribute-sync.js.map +2 -2
  48. package/dist/plugins/directives/boost.d.ts +1 -1
  49. package/dist/plugins/directives/boost.js +34 -30
  50. package/dist/plugins/directives/boost.js.map +2 -2
  51. package/dist/plugins/directives/busy-flag.js +13 -16
  52. package/dist/plugins/directives/busy-flag.js.map +2 -2
  53. package/dist/plugins/directives/class-toggle.js +17 -16
  54. package/dist/plugins/directives/class-toggle.js.map +2 -2
  55. package/dist/plugins/directives/cloak.js +2 -7
  56. package/dist/plugins/directives/cloak.js.map +2 -2
  57. package/dist/plugins/directives/collapse.js +36 -37
  58. package/dist/plugins/directives/collapse.js.map +2 -2
  59. package/dist/plugins/directives/declare.js +5 -8
  60. package/dist/plugins/directives/declare.js.map +2 -2
  61. package/dist/plugins/directives/derive.js +9 -15
  62. package/dist/plugins/directives/derive.js.map +2 -2
  63. package/dist/plugins/directives/element-ref.js +8 -8
  64. package/dist/plugins/directives/element-ref.js.map +2 -2
  65. package/dist/plugins/directives/event-listener.js +18 -23
  66. package/dist/plugins/directives/event-listener.js.map +2 -2
  67. package/dist/plugins/directives/frame-loop.js +9 -14
  68. package/dist/plugins/directives/frame-loop.js.map +2 -2
  69. package/dist/plugins/directives/html.js +6 -7
  70. package/dist/plugins/directives/html.js.map +2 -2
  71. package/dist/plugins/directives/inline-style.js +17 -20
  72. package/dist/plugins/directives/inline-style.js.map +2 -2
  73. package/dist/plugins/directives/mask.js +19 -23
  74. package/dist/plugins/directives/mask.js.map +2 -2
  75. package/dist/plugins/directives/media-query.d.ts +4 -1
  76. package/dist/plugins/directives/media-query.js +13 -12
  77. package/dist/plugins/directives/media-query.js.map +2 -2
  78. package/dist/plugins/directives/on-mount.js +4 -9
  79. package/dist/plugins/directives/on-mount.js.map +2 -2
  80. package/dist/plugins/directives/patch-listener.js +24 -19
  81. package/dist/plugins/directives/patch-listener.js.map +2 -2
  82. package/dist/plugins/directives/remove-me.js +7 -8
  83. package/dist/plugins/directives/remove-me.js.map +2 -2
  84. package/dist/plugins/directives/scroll-to.d.ts +4 -1
  85. package/dist/plugins/directives/scroll-to.js +8 -14
  86. package/dist/plugins/directives/scroll-to.js.map +2 -2
  87. package/dist/plugins/directives/size-watch.js +7 -12
  88. package/dist/plugins/directives/size-watch.js.map +2 -2
  89. package/dist/plugins/directives/state-dump.js +6 -10
  90. package/dist/plugins/directives/state-dump.js.map +2 -2
  91. package/dist/plugins/directives/storage-sync.js +13 -9
  92. package/dist/plugins/directives/storage-sync.js.map +2 -2
  93. package/dist/plugins/directives/teleport.js +8 -14
  94. package/dist/plugins/directives/teleport.js.map +2 -2
  95. package/dist/plugins/directives/text-content.js +6 -7
  96. package/dist/plugins/directives/text-content.js.map +2 -2
  97. package/dist/plugins/directives/timer.js +7 -13
  98. package/dist/plugins/directives/timer.js.map +2 -2
  99. package/dist/plugins/directives/transition.d.ts +1 -2
  100. package/dist/plugins/directives/transition.js +32 -34
  101. package/dist/plugins/directives/transition.js.map +2 -2
  102. package/dist/plugins/directives/tween.d.ts +2 -2
  103. package/dist/plugins/directives/tween.js +34 -50
  104. package/dist/plugins/directives/tween.js.map +2 -2
  105. package/dist/plugins/directives/two-way-bind.d.ts +1 -1
  106. package/dist/plugins/directives/two-way-bind.js +70 -67
  107. package/dist/plugins/directives/two-way-bind.js.map +2 -2
  108. package/dist/plugins/directives/url-params.js +36 -59
  109. package/dist/plugins/directives/url-params.js.map +3 -3
  110. package/dist/plugins/directives/url-replace.js +6 -7
  111. package/dist/plugins/directives/url-replace.js.map +2 -2
  112. package/dist/plugins/directives/validity.js +6 -9
  113. package/dist/plugins/directives/validity.js.map +2 -2
  114. package/dist/plugins/directives/viewport.js +18 -23
  115. package/dist/plugins/directives/viewport.js.map +2 -2
  116. package/dist/plugins/directives/visibility.js +9 -14
  117. package/dist/plugins/directives/visibility.js.map +2 -2
  118. package/dist/plugins/directives/watch.d.ts +0 -1
  119. package/dist/plugins/directives/watch.js +2 -8
  120. package/dist/plugins/directives/watch.js.map +2 -2
  121. package/dist/plugins/functions/bulk-set.js +10 -7
  122. package/dist/plugins/functions/bulk-set.js.map +2 -2
  123. package/dist/plugins/functions/bulk-toggle.js +10 -7
  124. package/dist/plugins/functions/bulk-toggle.js.map +2 -2
  125. package/dist/plugins/functions/confirm.js +2 -2
  126. package/dist/plugins/functions/confirm.js.map +2 -2
  127. package/dist/plugins/functions/copy-text.js +5 -5
  128. package/dist/plugins/functions/copy-text.js.map +2 -2
  129. package/dist/plugins/functions/dispatch.js +5 -5
  130. package/dist/plugins/functions/dispatch.js.map +2 -2
  131. package/dist/plugins/functions/locale-format.d.ts +4 -1
  132. package/dist/plugins/functions/locale-format.js +9 -16
  133. package/dist/plugins/functions/locale-format.js.map +2 -2
  134. package/dist/plugins/functions/range-map.js +6 -6
  135. package/dist/plugins/functions/range-map.js.map +2 -2
  136. package/dist/plugins/functions/request.d.ts +7 -3
  137. package/dist/plugins/functions/request.js +85 -80
  138. package/dist/plugins/functions/request.js.map +2 -2
  139. package/dist/plugins/functions/untracked-read.js +3 -2
  140. package/dist/plugins/functions/untracked-read.js.map +2 -2
  141. package/dist/plugins/functions/websocket.d.ts +3 -3
  142. package/dist/plugins/functions/websocket.js +18 -25
  143. package/dist/plugins/functions/websocket.js.map +2 -2
  144. package/dist/plugins/index.d.ts +34 -36
  145. package/dist/plugins/index.js +31 -35
  146. package/dist/plugins/index.js.map +2 -2
  147. package/dist/plugins/server-events/apply-elements.d.ts +1 -1
  148. package/dist/plugins/server-events/apply-elements.js +41 -40
  149. package/dist/plugins/server-events/apply-elements.js.map +2 -2
  150. package/dist/plugins/server-events/apply-state.js +9 -12
  151. package/dist/plugins/server-events/apply-state.js.map +2 -2
  152. package/dist/plugins/server-events/morph.d.ts +0 -2
  153. package/dist/plugins/server-events/morph.js +58 -55
  154. package/dist/plugins/server-events/morph.js.map +3 -3
  155. package/dist/presets/all.d.ts +0 -1
  156. package/dist/presets/all.js +22 -26
  157. package/dist/presets/all.js.map +2 -2
  158. package/dist/presets/essentials.d.ts +0 -1
  159. package/dist/presets/essentials.js +27 -9
  160. package/dist/presets/essentials.js.map +2 -2
  161. package/dist/presets/minimal.d.ts +0 -1
  162. package/dist/presets/minimal.js +2 -2
  163. package/dist/presets/minimal.js.map +2 -2
  164. package/dist/server.d.ts +108 -0
  165. package/dist/server.js +218 -0
  166. package/dist/server.js.map +7 -0
  167. package/dist/sigmx.standalone.js +1 -1
  168. package/dist/standalone.js.map +2 -2
  169. package/dist/vite.d.ts +2 -2
  170. package/dist/vite.js +48 -15
  171. package/dist/vite.js.map +2 -2
  172. package/package.json +21 -2
  173. package/dist/auto.d.ts +0 -1
  174. package/dist/auto.js +0 -7
  175. package/dist/auto.js.map +0 -7
  176. package/dist/core/csp.d.ts +0 -7
  177. package/dist/core/csp.js +0 -20
  178. package/dist/core/csp.js.map +0 -7
  179. package/dist/core/engine.d.ts +0 -10
  180. package/dist/core/engine.js +0 -200
  181. package/dist/core/engine.js.map +0 -7
  182. package/dist/core/expr.d.ts +0 -12
  183. package/dist/core/expr.js +0 -94
  184. package/dist/core/expr.js.map +0 -7
  185. package/dist/core/index.d.ts +0 -16
  186. package/dist/core/index.js +0 -46
  187. package/dist/core/index.js.map +0 -7
  188. package/dist/core/signals.d.ts +0 -42
  189. package/dist/core/signals.js +0 -195
  190. package/dist/core/signals.js.map +0 -7
  191. package/dist/core/store.d.ts +0 -32
  192. package/dist/core/store.js +0 -185
  193. package/dist/core/store.js.map +0 -7
  194. package/dist/core/types.d.ts +0 -101
  195. package/dist/core/types.js +0 -1
  196. package/dist/core/types.js.map +0 -7
  197. package/dist/plugins/actions/clipboard.d.ts +0 -2
  198. package/dist/plugins/actions/clipboard.js +0 -11
  199. package/dist/plugins/actions/clipboard.js.map +0 -7
  200. package/dist/plugins/actions/fit.d.ts +0 -2
  201. package/dist/plugins/actions/fit.js +0 -14
  202. package/dist/plugins/actions/fit.js.map +0 -7
  203. package/dist/plugins/actions/intl.d.ts +0 -2
  204. package/dist/plugins/actions/intl.js +0 -21
  205. package/dist/plugins/actions/intl.js.map +0 -7
  206. package/dist/plugins/actions/peek.d.ts +0 -2
  207. package/dist/plugins/actions/peek.js +0 -6
  208. package/dist/plugins/actions/peek.js.map +0 -7
  209. package/dist/plugins/actions/setAll.d.ts +0 -2
  210. package/dist/plugins/actions/setAll.js +0 -11
  211. package/dist/plugins/actions/setAll.js.map +0 -7
  212. package/dist/plugins/actions/toggleAll.d.ts +0 -2
  213. package/dist/plugins/actions/toggleAll.js +0 -11
  214. package/dist/plugins/actions/toggleAll.js.map +0 -7
  215. package/dist/plugins/attributes/attr.d.ts +0 -2
  216. package/dist/plugins/attributes/attr.js +0 -20
  217. package/dist/plugins/attributes/attr.js.map +0 -7
  218. package/dist/plugins/attributes/bind.d.ts +0 -6
  219. package/dist/plugins/attributes/bind.js +0 -81
  220. package/dist/plugins/attributes/bind.js.map +0 -7
  221. package/dist/plugins/attributes/class.d.ts +0 -2
  222. package/dist/plugins/attributes/class.js +0 -22
  223. package/dist/plugins/attributes/class.js.map +0 -7
  224. package/dist/plugins/attributes/computed.d.ts +0 -2
  225. package/dist/plugins/attributes/computed.js +0 -20
  226. package/dist/plugins/attributes/computed.js.map +0 -7
  227. package/dist/plugins/attributes/customValidity.d.ts +0 -2
  228. package/dist/plugins/attributes/customValidity.js +0 -14
  229. package/dist/plugins/attributes/customValidity.js.map +0 -7
  230. package/dist/plugins/attributes/effect.d.ts +0 -2
  231. package/dist/plugins/attributes/effect.js +0 -12
  232. package/dist/plugins/attributes/effect.js.map +0 -7
  233. package/dist/plugins/attributes/indicator.d.ts +0 -2
  234. package/dist/plugins/attributes/indicator.js +0 -20
  235. package/dist/plugins/attributes/indicator.js.map +0 -7
  236. package/dist/plugins/attributes/init.d.ts +0 -2
  237. package/dist/plugins/attributes/init.js +0 -14
  238. package/dist/plugins/attributes/init.js.map +0 -7
  239. package/dist/plugins/attributes/jsonSignals.d.ts +0 -2
  240. package/dist/plugins/attributes/jsonSignals.js +0 -15
  241. package/dist/plugins/attributes/jsonSignals.js.map +0 -7
  242. package/dist/plugins/attributes/matchMedia.d.ts +0 -2
  243. package/dist/plugins/attributes/matchMedia.js +0 -19
  244. package/dist/plugins/attributes/matchMedia.js.map +0 -7
  245. package/dist/plugins/attributes/on.d.ts +0 -5
  246. package/dist/plugins/attributes/on.js +0 -28
  247. package/dist/plugins/attributes/on.js.map +0 -7
  248. package/dist/plugins/attributes/onIntersect.d.ts +0 -2
  249. package/dist/plugins/attributes/onIntersect.js +0 -28
  250. package/dist/plugins/attributes/onIntersect.js.map +0 -7
  251. package/dist/plugins/attributes/onInterval.d.ts +0 -2
  252. package/dist/plugins/attributes/onInterval.js +0 -18
  253. package/dist/plugins/attributes/onInterval.js.map +0 -7
  254. package/dist/plugins/attributes/onRaf.d.ts +0 -1
  255. package/dist/plugins/attributes/onRaf.js +0 -19
  256. package/dist/plugins/attributes/onRaf.js.map +0 -7
  257. package/dist/plugins/attributes/onResize.d.ts +0 -1
  258. package/dist/plugins/attributes/onResize.js +0 -17
  259. package/dist/plugins/attributes/onResize.js.map +0 -7
  260. package/dist/plugins/attributes/onSignalPatch.d.ts +0 -5
  261. package/dist/plugins/attributes/onSignalPatch.js +0 -35
  262. package/dist/plugins/attributes/onSignalPatch.js.map +0 -7
  263. package/dist/plugins/attributes/persist.d.ts +0 -6
  264. package/dist/plugins/attributes/persist.js +0 -16
  265. package/dist/plugins/attributes/persist.js.map +0 -7
  266. package/dist/plugins/attributes/queryString.d.ts +0 -5
  267. package/dist/plugins/attributes/queryString.js +0 -54
  268. package/dist/plugins/attributes/queryString.js.map +0 -7
  269. package/dist/plugins/attributes/ref.d.ts +0 -2
  270. package/dist/plugins/attributes/ref.js +0 -13
  271. package/dist/plugins/attributes/ref.js.map +0 -7
  272. package/dist/plugins/attributes/replaceUrl.d.ts +0 -1
  273. package/dist/plugins/attributes/replaceUrl.js +0 -11
  274. package/dist/plugins/attributes/replaceUrl.js.map +0 -7
  275. package/dist/plugins/attributes/scrollIntoView.d.ts +0 -2
  276. package/dist/plugins/attributes/scrollIntoView.js +0 -19
  277. package/dist/plugins/attributes/scrollIntoView.js.map +0 -7
  278. package/dist/plugins/attributes/show.d.ts +0 -2
  279. package/dist/plugins/attributes/show.js +0 -19
  280. package/dist/plugins/attributes/show.js.map +0 -7
  281. package/dist/plugins/attributes/signals.d.ts +0 -2
  282. package/dist/plugins/attributes/signals.js +0 -13
  283. package/dist/plugins/attributes/signals.js.map +0 -7
  284. package/dist/plugins/attributes/style.d.ts +0 -2
  285. package/dist/plugins/attributes/style.js +0 -25
  286. package/dist/plugins/attributes/style.js.map +0 -7
  287. package/dist/plugins/attributes/text.d.ts +0 -1
  288. package/dist/plugins/attributes/text.js +0 -13
  289. package/dist/plugins/attributes/text.js.map +0 -7
  290. package/dist/plugins/attributes/viewTransition.d.ts +0 -1
  291. package/dist/plugins/attributes/viewTransition.js +0 -11
  292. package/dist/plugins/attributes/viewTransition.js.map +0 -7
  293. package/dist/plugins/directives/transition-name.d.ts +0 -1
  294. package/dist/plugins/directives/transition-name.js +0 -11
  295. package/dist/plugins/directives/transition-name.js.map +0 -7
  296. package/dist/plugins/directives/trap.d.ts +0 -5
  297. package/dist/plugins/directives/trap.js +0 -48
  298. package/dist/plugins/directives/trap.js.map +0 -7
  299. package/dist/sigmx.auto.js +0 -5
  300. package/dist/utils/object.d.ts +0 -9
  301. package/dist/utils/object.js +0 -26
  302. package/dist/utils/object.js.map +0 -7
  303. package/dist/utils/text.d.ts +0 -7
  304. package/dist/utils/text.js +0 -15
  305. package/dist/utils/text.js.map +0 -7
  306. package/dist/utils/timing.d.ts +0 -14
  307. package/dist/utils/timing.js +0 -58
  308. package/dist/utils/timing.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/runtime.ts"],
4
- "sourcesContent": ["import { functionCompiler } from './compile.js'\nimport { effect } from './reactive.js'\nimport { createStore } from './state.js'\nimport type { ActionCtx, AttributePlugin, Ctx, El, Evaluator, Mods, Plugin, Runtime, RuntimeOptions, Sigmx } from './contracts.js'\nimport { recase, type CaseStyle } from '../lib/casing.js'\n\nconst isEl = (n: Node): n is El => n instanceof HTMLElement || n instanceof SVGElement || n instanceof MathMLElement\n/** An element (or shadow root) followed by every element under it; nothing for text and comment nodes. */\nconst tree = (n: Node): El[] =>\n isEl(n) ? [n, ...n.querySelectorAll<El>('*')] : n instanceof ShadowRoot ? [...n.querySelectorAll<El>('*')] : []\n\ntype Parsed = { plugin: string; key: string | undefined; mods: Mods }\nconst parsed = new Map<string, Parsed>()\n\n/** 'on:click__debounce.300ms__prevent' \u2192 { plugin: 'on', key: 'click', mods: {debounce: ['300ms'], prevent: []} } */\nexport const parseAttr = (raw: string): Parsed => {\n let p = parsed.get(raw)\n if (!p) {\n const [head, ...modParts] = raw.split('__')\n const i = head.indexOf(':')\n const mods: Mods = new Map()\n for (const m of modParts) {\n const [name, ...args] = m.split('.')\n mods.set(name, args)\n }\n p = { plugin: i < 0 ? head : head.slice(0, i), key: i < 0 ? undefined : head.slice(i + 1), mods }\n parsed.set(raw, p)\n }\n return p\n}\n\nconst fail = (message: string, info: Record<string, unknown>): Error =>\n Object.assign(new Error(message), { info })\n\n/** Low-level constructor: you supply the expression pipeline. `createSigmx` wraps it with the runtime compiler. */\nexport const createRuntime = (options: RuntimeOptions): Sigmx => {\n const prefixes = ([] as string[]).concat(options.prefix ?? 'data-')\n const eventPrefixes = ([] as string[]).concat(options.eventPrefix ?? 'sigmx-')\n const store = options.store ?? createStore()\n const compiler = options.compile ?? functionCompiler\n const { expressions } = options\n const onError = options.onError ?? ((e, info) => console.error(e, info))\n const attributes: Record<string, AttributePlugin> = Object.create(null)\n const actions: Runtime['actions'] = Object.create(null)\n const handlers: Runtime['handlers'] = Object.create(null)\n\n const runtime: Runtime = {\n prefixes,\n attr: (name) => prefixes[0] + name,\n store,\n compiler,\n emit: (type, detail) => document.dispatchEvent(new CustomEvent(`sigmx-${type}`, { detail })),\n call: (name, ctx, args) => {\n const a = actions[name]\n if (!a) throw ctx.error(`unknown action @${name}`)\n return a.call(ctx, ...args)\n },\n eventPrefixes,\n handle: (event, data) => {\n const p = eventPrefixes.find((p) => event.startsWith(p))\n const h = handlers[p ? event.slice(p.length) : event]\n h?.handle(runtime, data)\n return !!h\n },\n attributes,\n actions,\n handlers,\n }\n\n // element \u2192 attribute name \u2192 dispose\n const mounted = new Map<El, Map<string, () => void>>()\n const roots = new Set<El | ShadowRoot>()\n const ignoreSelf = prefixes.map((p) => `[${p}ignore__self]`).join()\n const ignoreAny = prefixes.map((p) => `[${p}ignore]`).join()\n const ignored = (el: El) => el.matches(ignoreSelf) || !!el.closest(ignoreAny)\n\n const strip = (attr: string): string | undefined => {\n for (const p of prefixes) if (attr.startsWith(p)) return attr.slice(p.length)\n }\n\n const unmount = (els: Iterable<El>): void => {\n for (const el of els) {\n const m = mounted.get(el)\n if (m && mounted.delete(el)) for (const d of m.values()) d()\n }\n }\n\n const unmountAttr = (el: El, attr: string): void => {\n const m = mounted.get(el)\n m?.get(attr)?.()\n m?.delete(attr)\n }\n\n const actionsFor = (el: El, evt: Event | undefined, error: Ctx['error'], cleanup: (fn: () => void) => void) => {\n const ctx: ActionCtx = { el, evt, store, runtime, error, cleanup }\n return new Proxy({}, { get: (_, name: string) => (...args: any[]) => runtime.call(name, ctx, args) })\n }\n\n const mount = (el: El, attr: string, raw: string, value: string, only?: Set<string>): void => {\n const { plugin: name, key, mods } = parseAttr(raw)\n const plugin = attributes[name]\n if (!plugin || (only && !only.has(name))) return\n unmountAttr(el, attr)\n\n const disposers: (() => void)[] = []\n const info = { plugin: name, el, attr }\n const error: Ctx['error'] = (message, extra) => fail(`${prefixes[0]}${name}: ${message}`, { ...info, ...extra })\n const report = (e: unknown) => onError(e, info)\n let fn: Evaluator | undefined\n const ctx: Ctx = {\n el,\n plugin: name,\n attr,\n key,\n value,\n mods,\n cased: (style = 'camel') => recase(key ?? '', (mods.get('case')?.[0] as CaseStyle) || style),\n evaluate: (evt, ...args) => {\n fn ??= expressions(value, ['el', 'evt', ...(plugin.args ?? [])], plugin.returns ?? true)\n return fn(store, actionsFor(el, evt, error, ctx.cleanup), el, evt, ...args)\n },\n effect: (f) => disposers.push(effect(f, report)),\n listen: (target, type, f, opts) => {\n const h = (e: Event) => {\n try {\n f(e)\n } catch (err) {\n report(err)\n }\n }\n target.addEventListener(type, h, opts)\n disposers.push(() => target.removeEventListener(type, h, opts))\n },\n cleanup: (f) => disposers.push(f),\n error,\n store,\n runtime,\n }\n\n let m = mounted.get(el)\n if (!m) mounted.set(el, (m = new Map()))\n m.set(attr, () => {\n for (const d of disposers.splice(0)) d()\n })\n\n try {\n if (plugin.key === 'required' && !key) throw error('needs a key')\n if (plugin.key === 'forbidden' && key) throw error('takes no key')\n if (plugin.value === 'required' && !value) throw error('needs a value')\n if (plugin.value === 'forbidden' && value) throw error('takes no value')\n const r = plugin.mount(ctx)\n if (typeof r === 'function') disposers.push(r)\n } catch (e) {\n report(e)\n }\n }\n\n const mountEls = (els: Iterable<El>, only?: Set<string>): void => {\n for (const el of els) {\n if (ignored(el)) continue\n for (const { name, value } of [...el.attributes]) {\n const raw = strip(name)\n if (raw) mount(el, name, raw, value, only)\n }\n }\n }\n\n const observer = new MutationObserver((records) => {\n for (const { type, target, attributeName, addedNodes, removedNodes } of records) {\n if (type === 'childList') {\n for (const n of removedNodes) unmount(tree(n))\n for (const n of addedNodes) mountEls(tree(n))\n } else if (attributeName && isEl(target) && !ignored(target)) {\n const raw = strip(attributeName)\n if (!raw) continue\n const value = target.getAttribute(attributeName)\n if (value === null) unmountAttr(target, attributeName)\n else mount(target, attributeName, raw, value)\n }\n }\n })\n\n let ready = false\n const apply = (root: El | ShadowRoot = document.documentElement, observe = true, only?: Set<string>) => {\n mountEls(tree(root), only)\n if (observe && !roots.has(root)) {\n observer.observe(root, { subtree: true, childList: true, attributes: true })\n roots.add(root)\n }\n if (!ready && roots.has(document.documentElement)) {\n ready = true\n runtime.emit('ready')\n }\n }\n\n const use = (...plugins: Plugin[]): void => {\n const added = new Set<string>()\n for (const p of plugins) {\n if (p.type === 'attribute') {\n attributes[p.name] = p\n added.add(p.name)\n } else if (p.type === 'action') actions[p.name] = p\n else handlers[p.name] = p\n }\n if (added.size) for (const r of roots) apply(r, false, added)\n }\n\n const stopPatches = store.onPatch((patch) => runtime.emit('signal-patch', patch))\n use(...(options.plugins ?? []))\n\n const sigmx: Sigmx = {\n runtime,\n store,\n get $() {\n return store.$\n },\n apply: (root, observe) => apply(root, observe),\n use,\n destroy: () => {\n observer.disconnect()\n stopPatches()\n unmount([...mounted.keys()])\n roots.clear()\n },\n }\n\n if (options.autoStart ?? true) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => sigmx.apply(), { once: true })\n } else {\n sigmx.apply()\n }\n }\n return sigmx\n}\n"],
5
- "mappings": "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",
6
- "names": ["p"]
4
+ "sourcesContent": ["import { type CaseStyle, recase } from '../lib/casing.js';\nimport { functionCompiler } from './compile.js';\nimport type {\n ActionCtx,\n AttributePlugin,\n Ctx,\n El,\n Evaluator,\n Mods,\n Plugin,\n Runtime,\n RuntimeOptions,\n Sigmx,\n} from './contracts.js';\nimport { rootEffect } from './reactive.js';\nimport { createStore } from './state.js';\n\nconst isEl = (n: Node): n is El => n.nodeType === 1;\n/** An element (or shadow root) followed by every element under it; nothing for text and comment nodes. */\nconst tree = (n: Node): El[] =>\n (n as ParentNode).querySelectorAll ? [...(isEl(n) ? [n] : []), ...(n as ParentNode).querySelectorAll<El>('*')] : [];\n\ntype Parsed = { plugin: string; key: string | undefined; mods: Mods };\n\n/** 'on:click__debounce.300ms__prevent' \u2192 { plugin: 'on', key: 'click', mods: {debounce: ['300ms'], prevent: []} } */\nexport const parseAttr = (raw: string): Parsed => {\n const [head, ...modParts] = raw.split('__');\n const [, plugin, key] = /^([^:]*)(?::(.*))?$/.exec(head) as string[];\n return {\n plugin,\n key,\n mods: new Map(\n modParts.map((m) => {\n const [name, ...args] = m.split('.');\n return [name, args];\n }),\n ),\n };\n};\n\n/** The rest of `s` after the first prefix in `list` that it starts with; undefined when none matches. */\nconst cut = (list: readonly string[], s: string): string | undefined => {\n for (const p of list) if (s.startsWith(p)) return s.slice(p.length);\n};\n\n/** Low-level constructor: you supply the expression pipeline. `createSigmx` wraps it with the runtime compiler. */\nexport const createRuntime = (options: RuntimeOptions): Sigmx => {\n const prefixes = ([] as string[]).concat(options.prefix ?? 'data-');\n const eventPrefixes = ([] as string[]).concat(options.eventPrefix ?? 'sigmx-');\n const store = options.store ?? createStore();\n const { expressions } = options;\n const onError = options.onError ?? ((e, info) => console.error(e, info));\n const attributes: Record<string, AttributePlugin> = Object.create(null);\n\n const runtime: Runtime = {\n prefixes,\n attr: (name) => prefixes[0] + name,\n store,\n compiler: options.compile ?? functionCompiler,\n emit: (type, detail) => document.dispatchEvent(new CustomEvent(`sigmx-${type}`, { detail })),\n call: (name, ctx, args) => {\n const a = runtime.actions[name];\n if (!a) throw ctx.error(`unknown action @${name}`);\n return a.call(ctx, ...args);\n },\n eventPrefixes,\n handle: (event, data) => {\n const h = runtime.handlers[cut(eventPrefixes, event) ?? event];\n h?.handle(runtime, data);\n return !!h;\n },\n attributes,\n actions: Object.create(null),\n handlers: Object.create(null),\n };\n\n // element \u2192 attribute name \u2192 dispose\n const mounted = new Map<El, Map<string, () => void>>();\n const roots = new Set<El | ShadowRoot>();\n const ignoreAny = prefixes.map((p) => `[${p}ignore]`).join();\n const ignored = (el: El) => !!el.closest(ignoreAny);\n let destroyed = false;\n\n const unmount = (els: Iterable<El>): void => {\n for (const el of els) {\n const m = mounted.get(el);\n if (m && mounted.delete(el)) for (const d of m.values()) d();\n }\n };\n\n const unmountAttr = (el: El, attr: string): void => {\n const m = mounted.get(el);\n m?.get(attr)?.();\n m?.delete(attr);\n };\n\n const mount = (el: El, attr: string, raw: string, value: string, only?: Set<string>): void => {\n const { plugin: name, key, mods } = parseAttr(raw);\n const plugin = attributes[name];\n if (!plugin || (only && !only.has(name))) return;\n unmountAttr(el, attr);\n\n const disposers: (() => void)[] = [];\n const cleanup = (f: () => void) => {\n disposers.push(f);\n return () => {\n const i = disposers.indexOf(f);\n if (i >= 0) disposers.splice(i, 1);\n };\n };\n const info = { plugin: name, el, attr };\n const error: Ctx['error'] = (message, extra) =>\n Object.assign(new Error(`${prefixes[0]}${name}: ${message}`), { info: { ...info, ...extra } });\n const report = (e: unknown) => onError(e, info);\n let fn: Evaluator | undefined;\n const watched = new WeakSet<Promise<unknown>>(); // promises already routed to onError\n const watch = (r: unknown) => {\n if (r instanceof Promise && !watched.has(r)) {\n watched.add(r);\n r.catch(report);\n }\n };\n const ctx: Ctx = {\n el,\n plugin: name,\n attr,\n key,\n value,\n mods,\n cased: (style = 'camel') => recase(key ?? '', (mods.get('case')?.[0] as CaseStyle) || style),\n evaluate: (evt, ...args) => {\n if (plugin.literal && !mods.has('dynamic')) return value;\n fn ??= expressions(value, ['el', 'evt', ...(plugin.args ?? [])]);\n const actx: ActionCtx = { el, evt, store, runtime, error, cleanup, report };\n const actions = new Proxy(\n {},\n {\n get:\n (_, name: string) =>\n (...args: any[]) => {\n const r = runtime.call(name, actx, args);\n watch(r); // async actions (requests) reject long after the expression returned\n return r;\n },\n },\n );\n const r = fn(store, actions, el, evt, ...args);\n watch(r); // an expression's own rejected promise is reported too, once\n return r;\n },\n // Root-owned: an attribute mounted from inside another effect must outlive that effect's re-runs.\n effect: (f) => {\n cleanup(rootEffect(f, report));\n },\n listen: (target, type, f, opts) => {\n const h = (e: Event) => {\n try {\n f(e);\n } catch (err) {\n report(err);\n }\n };\n target.addEventListener(type, h, opts);\n cleanup(() => target.removeEventListener(type, h, opts));\n },\n cleanup,\n error,\n report,\n store,\n runtime,\n };\n\n let m = mounted.get(el);\n if (!m) {\n m = new Map();\n mounted.set(el, m);\n }\n m.set(attr, () => {\n for (const d of disposers.splice(0)) d();\n });\n\n try {\n // Contract checks: a keyed directive without a key would otherwise write to the path ''.\n for (const [k, v] of [\n ['key', key],\n ['value', value],\n ] as const) {\n const rule = plugin[k];\n if (rule && (rule === 'required') === !v) throw error(`${rule === 'required' ? 'needs a' : 'takes no'} ${k}`);\n }\n const r: unknown = plugin.mount(ctx);\n if (typeof r === 'function') cleanup(r as () => void);\n else watch(r); // an async mount that rejects is reported, not lost\n } catch (e) {\n report(e);\n }\n };\n\n const mountEls = (els: Iterable<El>, only?: Set<string>): void => {\n for (const el of els) {\n if (ignored(el)) continue;\n for (const { name, value } of [...el.attributes]) {\n const raw = cut(prefixes, name);\n // Observers can report a subtree more than once (nested insertions); a mounted attribute stays as it is.\n if (raw && !mounted.get(el)?.has(name)) mount(el, name, raw, value, only);\n }\n }\n };\n\n const observer = new MutationObserver((records) => {\n for (const { type, target, attributeName, addedNodes, removedNodes } of records) {\n if (type === 'childList') {\n // A node that is still connected was moved (teleport, morph), not removed: it keeps its state.\n for (const n of removedNodes) if (!n.isConnected) unmount(tree(n));\n for (const n of addedNodes) mountEls(tree(n));\n } else if (attributeName && isEl(target) && !ignored(target)) {\n const raw = cut(prefixes, attributeName);\n if (!raw) continue;\n const value = target.getAttribute(attributeName);\n if (value === null) unmountAttr(target, attributeName);\n else mount(target, attributeName, raw, value);\n }\n }\n });\n\n const apply = (root: El | ShadowRoot = document.documentElement, observe = true, only?: Set<string>) => {\n if (destroyed) return;\n mountEls(tree(root), only);\n if (observe && !roots.has(root)) {\n observer.observe(root, { subtree: true, childList: true, attributes: true });\n roots.add(root);\n }\n };\n\n const use = (...plugins: Plugin[]): void => {\n const added = new Set<string>();\n for (const p of plugins) {\n (runtime as any)[`${p.type}s`][p.name] = p;\n if (p.type === 'attribute') added.add(p.name);\n }\n if (added.size) for (const r of roots) apply(r, false, added);\n };\n\n const stopPatches = store.onPatch((patch) => runtime.emit('signal-patch', patch));\n use(...(options.plugins ?? []));\n\n const sigmx: Sigmx = {\n runtime,\n store,\n get $() {\n return store.$;\n },\n apply: (root, observe) => apply(root, observe),\n use,\n destroy: () => {\n destroyed = true;\n observer.disconnect();\n stopPatches();\n unmount([...mounted.keys()]);\n roots.clear();\n },\n };\n\n if (options.autoStart ?? true) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => sigmx.apply(), { once: true });\n } else {\n sigmx.apply();\n }\n }\n return sigmx;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["name", "args", "r"]
7
7
  }
@@ -1,18 +1,13 @@
1
1
  import type { Plugin } from './contracts.js';
2
2
  export type PluginMeta = {
3
- /** Export name, e.g. `httpGet`; what the generated module imports. */
4
3
  export: string;
5
- /** Registered name, e.g. `get`; what markup refers to. */
6
4
  name: string;
7
5
  type: Plugin['type'];
8
- /** Module to import from; built-ins come from `sigmx/plugins`. */
9
6
  from: string;
10
- returns?: boolean;
7
+ literal?: boolean;
11
8
  args?: string[];
12
9
  };
13
- /** Plugins that only make sense together. */
14
10
  export declare const implied: Record<string, string[]>;
15
- /** Metadata for every built-in plugin. */
16
11
  export declare const builtinPlugins: () => PluginMeta[];
17
12
  /**
18
13
  * Read a custom plugin's metadata from its source without executing it: finds
@@ -22,21 +17,17 @@ export declare const customPluginMeta: (exportName: string, source: string, from
22
17
  /** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */
23
18
  export declare const mentions: (source: string, p: PluginMeta, prefixes: string[]) => boolean;
24
19
  export type Selection = {
25
- /** Selected plugins in a stable order. */
26
20
  plugins: PluginMeta[];
27
- /** Why each one is in: 'used', 'always', or the plugin that implied it. */
28
21
  reasons: Record<string, string>;
29
- /** Known plugins that were left out. */
30
22
  unused: string[];
31
23
  };
32
24
  /**
33
25
  * Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from
34
26
  * `customPluginMeta`); `always` are export names that ship regardless.
35
27
  */
36
- export declare const selectPlugins: (sources: string[], { prefixes, always, custom }?: {
28
+ export declare const selectPlugins: (sources: string[], { prefixes, always, custom, }?: {
37
29
  prefixes?: string[];
38
30
  always?: string[];
39
31
  custom?: PluginMeta[];
40
32
  }) => Selection;
41
- /** JavaScript source for a module exporting `plugins` (and the selection report). */
42
33
  export declare const generatePluginsModule: (sel: Selection) => string;
@@ -6,34 +6,49 @@ const implied = {
6
6
  };
7
7
  const builtinPlugins = () => Object.entries(builtins).filter(([, v]) => v && typeof v === "object" && "type" in v).map(([key, v]) => {
8
8
  const p = v;
9
- return { export: key, name: p.name, type: p.type, from: "sigmx/plugins", returns: p.returns, args: p.args };
9
+ return {
10
+ export: key,
11
+ name: p.name,
12
+ type: p.type,
13
+ from: "sigmx/plugins",
14
+ literal: p.literal,
15
+ args: p.args
16
+ };
10
17
  });
11
18
  const customPluginMeta = (exportName, source, from) => {
12
- const re = new RegExp(`export\\s+const\\s+${exportName}\\s*(?::[^=]+)?=\\s*(attribute|action|handler)\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)`, "m");
19
+ const re = new RegExp(
20
+ `export\\s+const\\s+${exportName}\\s*(?::[^=]+)?=\\s*(attribute|action|handler)\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)`,
21
+ "m"
22
+ );
13
23
  const m = re.exec(source);
14
24
  if (!m) return;
15
25
  const body = m[2];
16
26
  const name = /\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(body)?.[1];
17
27
  if (!name) return;
18
- const returns = /\breturns\s*:\s*(true|false)/.exec(body)?.[1];
28
+ const literal = /\bliteral\s*:\s*true/.test(body);
19
29
  const args = /\bargs\s*:\s*\[([^\]]*)\]/.exec(body)?.[1];
20
30
  return {
21
31
  export: exportName,
22
32
  name,
23
33
  type: m[1],
24
34
  from,
25
- returns: returns === void 0 ? void 0 : returns === "true",
35
+ literal: literal || void 0,
26
36
  args: args?.split(",").map((s) => s.trim().replace(/^['"`]|['"`]$/g, "")).filter(Boolean)
27
37
  };
28
38
  };
29
- const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39
+ const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30
40
  const mentions = (source, p, prefixes) => {
31
- const n = escape(p.name);
32
- if (p.type === "attribute") return prefixes.some((pre) => new RegExp(`(^|[\\s"'\`<])${escape(pre)}${n}(?=[\\s=:_>"'\`/]|$)`, "m").test(source));
41
+ const n = esc(p.name);
42
+ if (p.type === "attribute")
43
+ return prefixes.some((pre) => new RegExp(`(^|[\\s"'\`<])${esc(pre)}${n}(?=[\\s=:_>"'\`/]|$)`, "m").test(source));
33
44
  if (p.type === "action") return new RegExp(`@${n}\\s*\\(`).test(source);
34
45
  return new RegExp(`['"\`](?:[\\w-]+-)?${n}['"\`]`).test(source);
35
46
  };
36
- const selectPlugins = (sources, { prefixes = ["data-"], always = [], custom = [] } = {}) => {
47
+ const selectPlugins = (sources, {
48
+ prefixes = ["data-"],
49
+ always = [],
50
+ custom = []
51
+ } = {}) => {
37
52
  const known = [...builtinPlugins(), ...custom];
38
53
  const byExport = new Map(known.map((p) => [p.export, p]));
39
54
  const reasons = {};
@@ -44,7 +59,9 @@ const selectPlugins = (sources, { prefixes = ["data-"], always = [], custom = []
44
59
  };
45
60
  for (const exp of always) add(exp, "always");
46
61
  const text = sources.join("\n");
47
- for (const p of known) if (!reasons[p.export] && (p.type !== "handler" || custom.includes(p)) && mentions(text, p, prefixes)) add(p.export, "used");
62
+ for (const p of known)
63
+ if (!reasons[p.export] && (p.type !== "handler" || custom.includes(p)) && mentions(text, p, prefixes))
64
+ add(p.export, "used");
48
65
  const plugins = known.filter((p) => reasons[p.export]);
49
66
  return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) };
50
67
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/scan.ts"],
4
- "sourcesContent": ["// Auto mode: work out which plugins a codebase uses by scanning its source, the way a CSS\n// framework scans templates for class names. Node only; never bundled for the browser.\nimport * as builtins from '../plugins/index.js'\nimport type { Plugin } from './contracts.js'\n\nexport type PluginMeta = {\n /** Export name, e.g. `httpGet`; what the generated module imports. */\n export: string\n /** Registered name, e.g. `get`; what markup refers to. */\n name: string\n type: Plugin['type']\n /** Module to import from; built-ins come from `sigmx/plugins`. */\n from: string\n returns?: boolean\n args?: string[]\n}\n\nconst NETWORK = ['httpGet', 'httpPost', 'httpPut', 'httpPatch', 'httpDelete', 'websocket', 'boost']\n\n/** Plugins that only make sense together. */\nexport const implied: Record<string, string[]> = {\n ...Object.fromEntries(NETWORK.map((n) => [n, ['applyElements', 'applyState']])),\n boost: ['httpGet', 'httpPost', 'applyElements', 'applyState'],\n}\n\n/** Metadata for every built-in plugin. */\nexport const builtinPlugins = (): PluginMeta[] =>\n Object.entries(builtins)\n .filter(([, v]) => v && typeof v === 'object' && 'type' in (v as object))\n .map(([key, v]) => {\n const p = v as Plugin\n return { export: key, name: p.name, type: p.type, from: 'sigmx/plugins', returns: (p as any).returns, args: (p as any).args }\n })\n\n/**\n * Read a custom plugin's metadata from its source without executing it: finds\n * `attribute({ name: 'x', ... })`, `action({...})` or `handler({...})` near `export const <exportName>`.\n */\nexport const customPluginMeta = (exportName: string, source: string, from: string): PluginMeta | undefined => {\n const re = new RegExp(`export\\\\s+const\\\\s+${exportName}\\\\s*(?::[^=]+)?=\\\\s*(attribute|action|handler)\\\\s*\\\\(\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*\\\\)`, 'm')\n const m = re.exec(source)\n if (!m) return\n const body = m[2]\n const name = /\\bname\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(body)?.[1]\n if (!name) return\n const returns = /\\breturns\\s*:\\s*(true|false)/.exec(body)?.[1]\n const args = /\\bargs\\s*:\\s*\\[([^\\]]*)\\]/.exec(body)?.[1]\n return {\n export: exportName,\n name,\n type: m[1] as Plugin['type'],\n from,\n returns: returns === undefined ? undefined : returns === 'true',\n args: args?.split(',').map((s) => s.trim().replace(/^['\"`]|['\"`]$/g, '')).filter(Boolean),\n }\n}\n\nconst escape = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n/** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */\nexport const mentions = (source: string, p: PluginMeta, prefixes: string[]): boolean => {\n const n = escape(p.name)\n if (p.type === 'attribute') return prefixes.some((pre) => new RegExp(`(^|[\\\\s\"'\\`<])${escape(pre)}${n}(?=[\\\\s=:_>\"'\\`/]|$)`, 'm').test(source))\n if (p.type === 'action') return new RegExp(`@${n}\\\\s*\\\\(`).test(source)\n return new RegExp(`['\"\\`](?:[\\\\w-]+-)?${n}['\"\\`]`).test(source)\n}\n\nexport type Selection = {\n /** Selected plugins in a stable order. */\n plugins: PluginMeta[]\n /** Why each one is in: 'used', 'always', or the plugin that implied it. */\n reasons: Record<string, string>\n /** Known plugins that were left out. */\n unused: string[]\n}\n\n/**\n * Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from\n * `customPluginMeta`); `always` are export names that ship regardless.\n */\nexport const selectPlugins = (\n sources: string[],\n { prefixes = ['data-'], always = [], custom = [] }: { prefixes?: string[]; always?: string[]; custom?: PluginMeta[] } = {},\n): Selection => {\n const known = [...builtinPlugins(), ...custom]\n const byExport = new Map(known.map((p) => [p.export, p]))\n const reasons: Record<string, string> = {}\n const add = (exp: string, why: string) => {\n if (!byExport.has(exp) || reasons[exp]) return\n reasons[exp] = why\n for (const dep of implied[exp] ?? []) add(dep, exp)\n }\n for (const exp of always) add(exp, 'always')\n const text = sources.join('\\n')\n for (const p of known) if (!reasons[p.export] && (p.type !== 'handler' || custom.includes(p)) && mentions(text, p, prefixes)) add(p.export, 'used')\n const plugins = known.filter((p) => reasons[p.export])\n return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) }\n}\n\n/** JavaScript source for a module exporting `plugins` (and the selection report). */\nexport const generatePluginsModule = (sel: Selection): string => {\n const groups = new Map<string, string[]>()\n for (const p of sel.plugins) groups.set(p.from, [...(groups.get(p.from) ?? []), p.export])\n const imports = [...groups].map(([from, names]) => `import { ${names.join(', ')} } from ${JSON.stringify(from)}`).join('\\n')\n return `${imports}\\nexport const plugins = [${sel.plugins.map((p) => p.export).join(', ')}]\\nexport const report = ${JSON.stringify({ reasons: sel.reasons, unused: sel.unused }, null, 2)}\\n`\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Node only; never bundled for the browser.\nimport * as builtins from '../plugins/index.js';\nimport type { Plugin } from './contracts.js';\n\nexport type PluginMeta = {\n export: string;\n name: string;\n type: Plugin['type'];\n from: string;\n literal?: boolean;\n args?: string[];\n};\n\nconst NETWORK = ['httpGet', 'httpPost', 'httpPut', 'httpPatch', 'httpDelete', 'websocket', 'boost'];\n\nexport const implied: Record<string, string[]> = {\n ...Object.fromEntries(NETWORK.map((n) => [n, ['applyElements', 'applyState']])),\n boost: ['httpGet', 'httpPost', 'applyElements', 'applyState'],\n};\n\nexport const builtinPlugins = (): PluginMeta[] =>\n Object.entries(builtins)\n .filter(([, v]) => v && typeof v === 'object' && 'type' in (v as object))\n .map(([key, v]) => {\n const p = v as Plugin;\n return {\n export: key,\n name: p.name,\n type: p.type,\n from: 'sigmx/plugins',\n literal: (p as any).literal,\n args: (p as any).args,\n };\n });\n\n/**\n * Read a custom plugin's metadata from its source without executing it: finds\n * `attribute({ name: 'x', ... })`, `action({...})` or `handler({...})` near `export const <exportName>`.\n */\nexport const customPluginMeta = (exportName: string, source: string, from: string): PluginMeta | undefined => {\n const re = new RegExp(\n `export\\\\s+const\\\\s+${exportName}\\\\s*(?::[^=]+)?=\\\\s*(attribute|action|handler)\\\\s*\\\\(\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*\\\\)`,\n 'm',\n );\n const m = re.exec(source);\n if (!m) return;\n const body = m[2];\n const name = /\\bname\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(body)?.[1];\n if (!name) return;\n const literal = /\\bliteral\\s*:\\s*true/.test(body);\n const args = /\\bargs\\s*:\\s*\\[([^\\]]*)\\]/.exec(body)?.[1];\n return {\n export: exportName,\n name,\n type: m[1] as Plugin['type'],\n from,\n literal: literal || undefined,\n args: args\n ?.split(',')\n .map((s) => s.trim().replace(/^['\"`]|['\"`]$/g, ''))\n .filter(Boolean),\n };\n};\n\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */\nexport const mentions = (source: string, p: PluginMeta, prefixes: string[]): boolean => {\n const n = esc(p.name);\n if (p.type === 'attribute')\n return prefixes.some((pre) => new RegExp(`(^|[\\\\s\"'\\`<])${esc(pre)}${n}(?=[\\\\s=:_>\"'\\`/]|$)`, 'm').test(source));\n if (p.type === 'action') return new RegExp(`@${n}\\\\s*\\\\(`).test(source);\n return new RegExp(`['\"\\`](?:[\\\\w-]+-)?${n}['\"\\`]`).test(source);\n};\n\nexport type Selection = {\n plugins: PluginMeta[];\n reasons: Record<string, string>;\n unused: string[];\n};\n\n/**\n * Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from\n * `customPluginMeta`); `always` are export names that ship regardless.\n */\nexport const selectPlugins = (\n sources: string[],\n {\n prefixes = ['data-'],\n always = [],\n custom = [],\n }: { prefixes?: string[]; always?: string[]; custom?: PluginMeta[] } = {},\n): Selection => {\n const known = [...builtinPlugins(), ...custom];\n const byExport = new Map(known.map((p) => [p.export, p]));\n const reasons: Record<string, string> = {};\n const add = (exp: string, why: string) => {\n if (!byExport.has(exp) || reasons[exp]) return;\n reasons[exp] = why;\n for (const dep of implied[exp] ?? []) add(dep, exp);\n };\n for (const exp of always) add(exp, 'always');\n const text = sources.join('\\n');\n for (const p of known)\n if (!reasons[p.export] && (p.type !== 'handler' || custom.includes(p)) && mentions(text, p, prefixes))\n add(p.export, 'used');\n const plugins = known.filter((p) => reasons[p.export]);\n return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) };\n};\n\nexport const generatePluginsModule = (sel: Selection): string => {\n const groups = new Map<string, string[]>();\n for (const p of sel.plugins) groups.set(p.from, [...(groups.get(p.from) ?? []), p.export]);\n const imports = [...groups]\n .map(([from, names]) => `import { ${names.join(', ')} } from ${JSON.stringify(from)}`)\n .join('\\n');\n return `${imports}\\nexport const plugins = [${sel.plugins.map((p) => p.export).join(', ')}]\\nexport const report = ${JSON.stringify({ reasons: sel.reasons, unused: sel.unused }, null, 2)}\\n`;\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
- import { Signal } from './reactive.js';
2
1
  import { type Filter } from '../lib/objects.js';
2
+ import { Signal } from './reactive.js';
3
3
  export type Patch = Record<string, any>;
4
4
  export interface Store {
5
5
  /** Value at a dotted path: a leaf value, a namespace proxy, or undefined. Reads subscribe. */
@@ -13,20 +13,17 @@ export interface Store {
13
13
  }): void;
14
14
  remove(path: string): void;
15
15
  has(path: string): boolean;
16
- /** Install a computed (or any signal) as the leaf at a path. */
17
16
  define(path: string, node: Signal<any>): void;
18
- /** Leaf paths, optionally filtered. */
19
- paths(filter?: Filter): string[];
20
- /** Plain-object copy of the store or a namespace. */
17
+ /** Leaf paths, filtered; `computed: false` leaves out computed signals. */
18
+ paths(filter?: Filter, options?: {
19
+ computed?: boolean;
20
+ }): string[];
21
21
  snapshot(filter?: Filter, options?: {
22
22
  at?: string;
23
23
  computed?: boolean;
24
24
  }): Patch;
25
25
  /** Called after each settled batch with the nested object of changed paths (null = removed). */
26
26
  onPatch(fn: (patch: Patch) => void): () => void;
27
- /** Root namespace proxy: `$.count`, `$.user.name = 'x'`, `JSON.stringify($)`. */
28
27
  readonly $: any;
29
- /** Identifier scope for compiled expressions: resolves `$count`, `$user`, and `$`. */
30
- readonly scope: object;
31
28
  }
32
29
  export declare const createStore: () => Store;
@@ -1,10 +1,13 @@
1
- import { Computed, Signal, batch, onSettled } from "./reactive.js";
2
- import { expand, isPlain, toPredicate } from "../lib/objects.js";
3
- const parentOf = (p) => p.slice(0, Math.max(0, p.lastIndexOf(".")));
4
- const nameOf = (p) => p.slice(p.lastIndexOf(".") + 1);
1
+ import { expand, isPlain, safeKey, toPredicate } from "../lib/objects.js";
2
+ import { batch, Computed, onSettled, Signal } from "./reactive.js";
3
+ const split = (p) => {
4
+ const i = p.lastIndexOf(".");
5
+ return [i < 0 ? "" : p.slice(0, i), p.slice(i + 1)];
6
+ };
5
7
  const join = (a, b) => a ? `${a}.${b}` : b;
6
- const under = (p, at) => !at || p === at || p.startsWith(`${at}.`);
8
+ const under = (p, at) => !at || p.startsWith(`${at}.`);
7
9
  const str = (k) => typeof k === "string";
10
+ const rawOf = /* @__PURE__ */ new WeakMap();
8
11
  const createStore = () => {
9
12
  const leaves = /* @__PURE__ */ new Map();
10
13
  const kids = /* @__PURE__ */ new Map([["", /* @__PURE__ */ new Set()]]);
@@ -12,14 +15,24 @@ const createStore = () => {
12
15
  const pending = /* @__PURE__ */ new Map();
13
16
  const listeners = /* @__PURE__ */ new Set();
14
17
  const nsCache = /* @__PURE__ */ new Map();
15
- const arrCache = /* @__PURE__ */ new WeakMap();
18
+ const proxies = /* @__PURE__ */ new WeakMap();
19
+ const link = (p) => {
20
+ const [parent, name] = split(p);
21
+ ensureNs(parent).add(name);
22
+ shape.bump();
23
+ };
24
+ const unlink = (p) => {
25
+ const [parent, name] = split(p);
26
+ kids.get(parent)?.delete(name);
27
+ shape.bump();
28
+ };
16
29
  const ensureNs = (p) => {
17
30
  let set2 = kids.get(p);
18
31
  if (!set2) {
19
32
  if (leaves.has(p)) dropLeaf(p);
20
- kids.set(p, set2 = /* @__PURE__ */ new Set());
21
- ensureNs(parentOf(p)).add(nameOf(p));
22
- shape.bump();
33
+ set2 = /* @__PURE__ */ new Set();
34
+ kids.set(p, set2);
35
+ link(p);
23
36
  }
24
37
  return set2;
25
38
  };
@@ -27,10 +40,10 @@ const createStore = () => {
27
40
  const s = leaves.get(p);
28
41
  if (!s) return;
29
42
  leaves.delete(p);
30
- kids.get(parentOf(p))?.delete(nameOf(p));
43
+ unlink(p);
31
44
  pending.set(p, null);
32
45
  s.bump();
33
- shape.bump();
46
+ if (s instanceof Computed) s.dispose();
34
47
  };
35
48
  const dropNs = (p) => {
36
49
  const set2 = kids.get(p);
@@ -38,34 +51,35 @@ const createStore = () => {
38
51
  for (const k of [...set2]) remove(join(p, k));
39
52
  if (p) {
40
53
  kids.delete(p);
41
- kids.get(parentOf(p))?.delete(nameOf(p));
42
54
  nsCache.delete(p);
55
+ unlink(p);
43
56
  }
44
- shape.bump();
45
57
  };
46
58
  const remove = (p) => batch(() => {
47
59
  dropLeaf(p);
48
60
  dropNs(p);
49
61
  });
50
62
  const define = (p, node) => batch(() => {
51
- if (kids.has(p)) dropNs(p);
63
+ dropNs(p);
52
64
  const old = leaves.get(p);
53
65
  leaves.set(p, node);
54
- ensureNs(parentOf(p)).add(nameOf(p));
55
- old?.bump();
56
- shape.bump();
66
+ link(p);
67
+ if (old) {
68
+ old.bump();
69
+ if (old instanceof Computed) old.dispose();
70
+ }
57
71
  });
58
72
  const set = (p, v) => batch(() => {
59
73
  if (v == null) return remove(p);
74
+ v = (v && rawOf.get(v)) ?? v;
60
75
  if (isPlain(v)) {
61
- const names = ensureNs(p);
62
- for (const k of [...names]) if (!(k in v)) remove(join(p, k));
63
- for (const k in v) set(join(p, k), v[k]);
76
+ for (const k of [...ensureNs(p)]) if (!(k in v)) remove(join(p, k));
77
+ for (const k in v) if (safeKey(k)) set(join(p, k), v[k]);
64
78
  return;
65
79
  }
66
- if (kids.has(p)) dropNs(p);
80
+ dropNs(p);
67
81
  const s = leaves.get(p);
68
- if (s instanceof Computed) throw new Error(`"${p}" is a computed signal and cannot be assigned`);
82
+ if (s instanceof Computed) throw new Error(`computed "${p}" is read-only`);
69
83
  if (s) {
70
84
  if (Object.is(s.peek(), v)) return;
71
85
  s.value = v;
@@ -76,33 +90,57 @@ const createStore = () => {
76
90
  });
77
91
  const merge = (patch, { at = "", ifMissing = false } = {}) => batch(() => {
78
92
  if (!isPlain(patch)) return;
79
- ensureNs(at);
80
- for (const k in patch) {
93
+ const keys = Object.keys(patch).filter(safeKey);
94
+ if (keys.length) ensureNs(at);
95
+ for (const k of keys) {
81
96
  const p = join(at, k);
82
97
  const v = patch[k];
98
+ const leaf = leaves.get(p);
99
+ if (leaf && (ifMissing || leaf instanceof Computed)) continue;
83
100
  if (v === null) {
84
101
  if (!ifMissing) remove(p);
85
- } else if (isPlain(v)) {
86
- merge(v, { at: p, ifMissing });
87
- } else if (!(ifMissing && (leaves.has(p) || kids.has(p))) && !(leaves.get(p) instanceof Computed)) {
88
- set(p, v);
89
- }
102
+ } else if (isPlain(v)) merge(v, { at: p, ifMissing });
103
+ else if (!(ifMissing && kids.has(p))) set(p, v);
90
104
  }
91
105
  });
106
+ const has = (p) => leaves.has(p) || kids.has(p);
92
107
  const wrapArray = (raw, s, p) => {
93
- let px = arrCache.get(raw);
94
- if (!px) {
95
- const touch = () => {
96
- pending.set(p, raw);
97
- s.bump();
98
- };
99
- px = new Proxy(raw, {
100
- set: (t, k, v) => (t[k] = v, touch(), true),
101
- deleteProperty: (t, k) => (delete t[k], touch(), true)
102
- });
103
- arrCache.set(raw, px);
108
+ let cache = proxies.get(s);
109
+ if (!cache) {
110
+ cache = /* @__PURE__ */ new WeakMap();
111
+ proxies.set(s, cache);
104
112
  }
105
- return px;
113
+ const touch = () => {
114
+ pending.set(p, raw);
115
+ s.bump();
116
+ return true;
117
+ };
118
+ const wrap = (target) => {
119
+ let px = cache?.get(target);
120
+ if (!px) {
121
+ px = new Proxy(target, {
122
+ get: (t, k, r) => {
123
+ const v = Reflect.get(t, k, r);
124
+ if (typeof v === "function" && Array.isArray(t)) return (...a) => batch(() => v.apply(r, a));
125
+ if (!v || typeof v !== "object" || !(Array.isArray(v) || isPlain(v))) return v;
126
+ const d = Object.getOwnPropertyDescriptor(t, k);
127
+ return d && !d.configurable && !d.writable ? v : wrap(v);
128
+ },
129
+ set: (t, k, v) => {
130
+ t[k] = (v && rawOf.get(v)) ?? v;
131
+ return touch();
132
+ },
133
+ deleteProperty: (t, k) => {
134
+ delete t[k];
135
+ return touch();
136
+ }
137
+ });
138
+ cache?.set(target, px);
139
+ rawOf.set(px, target);
140
+ }
141
+ return px;
142
+ };
143
+ return wrap(raw);
106
144
  };
107
145
  const get = (p) => {
108
146
  const s = leaves.get(p);
@@ -110,51 +148,49 @@ const createStore = () => {
110
148
  const v = s.value;
111
149
  return Array.isArray(v) ? wrapArray(v, s, p) : v;
112
150
  }
113
- if (kids.has(p)) return ns(p);
114
151
  shape.value;
115
- return void 0;
152
+ if (kids.has(p)) return ns(p);
116
153
  };
117
154
  const ns = (p) => {
118
155
  let px = nsCache.get(p);
119
156
  if (!px) {
120
- const names = () => (shape.value, kids.get(p));
121
- px = new Proxy({}, {
122
- get: (_, k) => !str(k) ? void 0 : k === "toJSON" ? () => snapshot(void 0, { at: p }) : get(join(p, k)),
123
- set: (_, k, v) => (str(k) && set(join(p, k), v), true),
124
- deleteProperty: (_, k) => (str(k) && remove(join(p, k)), true),
125
- has: (_, k) => str(k) && !!names()?.has(k),
126
- ownKeys: () => [...names() ?? []],
127
- getOwnPropertyDescriptor: (_, k) => str(k) && names()?.has(k) ? { enumerable: true, configurable: true, writable: true, value: get(join(p, k)) } : void 0
128
- });
157
+ const names = (k) => {
158
+ shape.value;
159
+ return str(k) && !!kids.get(p)?.has(k);
160
+ };
161
+ px = new Proxy(
162
+ {},
163
+ {
164
+ get: (_, k) => !str(k) ? void 0 : k === "toJSON" ? () => snapshot(void 0, { at: p }) : get(join(p, k)),
165
+ set: (_, k, v) => {
166
+ if (str(k)) set(join(p, k), v);
167
+ return true;
168
+ },
169
+ deleteProperty: (_, k) => {
170
+ if (str(k)) remove(join(p, k));
171
+ return true;
172
+ },
173
+ has: (_, k) => names(k),
174
+ ownKeys: () => {
175
+ shape.value;
176
+ return [...kids.get(p) ?? []];
177
+ },
178
+ getOwnPropertyDescriptor: (_, k) => names(k) ? { enumerable: true, configurable: true, writable: true, value: get(join(p, k)) } : void 0
179
+ }
180
+ );
129
181
  nsCache.set(p, px);
130
182
  }
131
183
  return px;
132
184
  };
133
- const scope = new Proxy({}, {
134
- has: (_, k) => str(k) && k[0] === "$",
135
- get: (_, k) => !str(k) ? void 0 : k === "$" ? ns("") : get(k.slice(1)),
136
- set: (_, k, v) => {
137
- if (str(k)) k === "$" ? merge(v) : set(k.slice(1), v);
138
- return true;
139
- }
140
- });
141
- const paths = (filter) => {
185
+ const paths = (filter, { computed = true } = {}) => {
142
186
  shape.value;
143
187
  const ok = toPredicate(filter);
144
- return [...leaves.keys()].filter(ok);
188
+ return [...leaves].filter(([p, s]) => ok(p) && (computed || !(s instanceof Computed))).map(([p]) => p);
145
189
  };
146
190
  const snapshot = (filter, { at = "", computed = true } = {}) => {
147
- shape.value;
148
- const ok = toPredicate(filter);
149
191
  const out = {};
150
- const rel = (p) => at ? p.slice(at.length + 1) : p;
151
- for (const [p, s] of leaves) {
152
- if (!under(p, at) || !ok(p) || !computed && s instanceof Computed) continue;
153
- expand(out, rel(p), s.value);
154
- }
155
- for (const p of kids.keys()) {
156
- if (p && p !== at && under(p, at) && ok(p) && !kids.get(p).size) expand(out, rel(p), {});
157
- }
192
+ for (const p of paths(filter, { computed }))
193
+ if (under(p, at)) expand(out, at ? p.slice(at.length + 1) : p, leaves.get(p)?.value);
158
194
  return out;
159
195
  };
160
196
  onSettled(() => {
@@ -169,15 +205,17 @@ const createStore = () => {
169
205
  set,
170
206
  merge,
171
207
  remove,
172
- has: (p) => leaves.has(p) || kids.has(p),
208
+ has,
173
209
  define,
174
210
  paths,
175
211
  snapshot,
176
- onPatch: (fn) => (listeners.add(fn), () => listeners.delete(fn)),
212
+ onPatch: (fn) => {
213
+ listeners.add(fn);
214
+ return () => listeners.delete(fn);
215
+ },
177
216
  get $() {
178
217
  return ns("");
179
- },
180
- scope
218
+ }
181
219
  };
182
220
  };
183
221
  export {