sigmx 0.1.1 → 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 (165) hide show
  1. package/README.md +10 -10
  2. package/dist/kernel/compile.d.ts +8 -9
  3. package/dist/kernel/compile.js +102 -67
  4. package/dist/kernel/compile.js.map +2 -2
  5. package/dist/kernel/contracts.d.ts +11 -5
  6. package/dist/kernel/index.d.ts +2 -2
  7. package/dist/kernel/index.js +5 -6
  8. package/dist/kernel/index.js.map +2 -2
  9. package/dist/kernel/precompile.d.ts +8 -10
  10. package/dist/kernel/precompile.js +25 -75
  11. package/dist/kernel/precompile.js.map +2 -2
  12. package/dist/kernel/precompiled.d.ts +7 -4
  13. package/dist/kernel/precompiled.js +5 -5
  14. package/dist/kernel/precompiled.js.map +2 -2
  15. package/dist/kernel/reactive.d.ts +8 -2
  16. package/dist/kernel/reactive.js +91 -62
  17. package/dist/kernel/reactive.js.map +3 -3
  18. package/dist/kernel/runtime.js +78 -68
  19. package/dist/kernel/runtime.js.map +3 -3
  20. package/dist/kernel/scan.d.ts +1 -1
  21. package/dist/kernel/scan.js +3 -3
  22. package/dist/kernel/scan.js.map +2 -2
  23. package/dist/kernel/state.d.ts +4 -3
  24. package/dist/kernel/state.js +91 -80
  25. package/dist/kernel/state.js.map +2 -2
  26. package/dist/kernel/strict-csp.d.ts +0 -5
  27. package/dist/kernel/strict-csp.js +2 -2
  28. package/dist/kernel/strict-csp.js.map +2 -2
  29. package/dist/lib/casing.d.ts +4 -1
  30. package/dist/lib/casing.js +8 -1
  31. package/dist/lib/casing.js.map +2 -2
  32. package/dist/lib/objects.d.ts +5 -3
  33. package/dist/lib/objects.js +10 -5
  34. package/dist/lib/objects.js.map +2 -2
  35. package/dist/lib/schedule.d.ts +3 -3
  36. package/dist/lib/schedule.js +12 -10
  37. package/dist/lib/schedule.js.map +2 -2
  38. package/dist/lib/sse.d.ts +10 -0
  39. package/dist/lib/sse.js +32 -29
  40. package/dist/lib/sse.js.map +2 -2
  41. package/dist/plugins/def.d.ts +5 -0
  42. package/dist/plugins/def.js +22 -0
  43. package/dist/plugins/def.js.map +7 -0
  44. package/dist/plugins/directives/attribute-sync.js +8 -12
  45. package/dist/plugins/directives/attribute-sync.js.map +2 -2
  46. package/dist/plugins/directives/boost.d.ts +1 -1
  47. package/dist/plugins/directives/boost.js +34 -31
  48. package/dist/plugins/directives/boost.js.map +2 -2
  49. package/dist/plugins/directives/busy-flag.js +13 -16
  50. package/dist/plugins/directives/busy-flag.js.map +2 -2
  51. package/dist/plugins/directives/class-toggle.js +17 -16
  52. package/dist/plugins/directives/class-toggle.js.map +2 -2
  53. package/dist/plugins/directives/cloak.js +2 -7
  54. package/dist/plugins/directives/cloak.js.map +2 -2
  55. package/dist/plugins/directives/collapse.js +36 -37
  56. package/dist/plugins/directives/collapse.js.map +2 -2
  57. package/dist/plugins/directives/declare.js +5 -8
  58. package/dist/plugins/directives/declare.js.map +2 -2
  59. package/dist/plugins/directives/derive.js +9 -18
  60. package/dist/plugins/directives/derive.js.map +2 -2
  61. package/dist/plugins/directives/element-ref.js +8 -8
  62. package/dist/plugins/directives/element-ref.js.map +2 -2
  63. package/dist/plugins/directives/event-listener.js +18 -26
  64. package/dist/plugins/directives/event-listener.js.map +2 -2
  65. package/dist/plugins/directives/frame-loop.js +9 -14
  66. package/dist/plugins/directives/frame-loop.js.map +2 -2
  67. package/dist/plugins/directives/html.js +6 -7
  68. package/dist/plugins/directives/html.js.map +2 -2
  69. package/dist/plugins/directives/inline-style.js +17 -20
  70. package/dist/plugins/directives/inline-style.js.map +2 -2
  71. package/dist/plugins/directives/mask.js +19 -23
  72. package/dist/plugins/directives/mask.js.map +2 -2
  73. package/dist/plugins/directives/media-query.d.ts +4 -1
  74. package/dist/plugins/directives/media-query.js +13 -13
  75. package/dist/plugins/directives/media-query.js.map +2 -2
  76. package/dist/plugins/directives/on-mount.js +4 -12
  77. package/dist/plugins/directives/on-mount.js.map +2 -2
  78. package/dist/plugins/directives/patch-listener.js +24 -19
  79. package/dist/plugins/directives/patch-listener.js.map +2 -2
  80. package/dist/plugins/directives/remove-me.js +7 -8
  81. package/dist/plugins/directives/remove-me.js.map +2 -2
  82. package/dist/plugins/directives/scroll-to.d.ts +4 -1
  83. package/dist/plugins/directives/scroll-to.js +8 -14
  84. package/dist/plugins/directives/scroll-to.js.map +2 -2
  85. package/dist/plugins/directives/size-watch.js +7 -12
  86. package/dist/plugins/directives/size-watch.js.map +2 -2
  87. package/dist/plugins/directives/state-dump.js +6 -10
  88. package/dist/plugins/directives/state-dump.js.map +2 -2
  89. package/dist/plugins/directives/storage-sync.js +13 -9
  90. package/dist/plugins/directives/storage-sync.js.map +2 -2
  91. package/dist/plugins/directives/teleport.js +8 -14
  92. package/dist/plugins/directives/teleport.js.map +2 -2
  93. package/dist/plugins/directives/text-content.js +6 -7
  94. package/dist/plugins/directives/text-content.js.map +2 -2
  95. package/dist/plugins/directives/timer.js +7 -13
  96. package/dist/plugins/directives/timer.js.map +2 -2
  97. package/dist/plugins/directives/transition.d.ts +1 -2
  98. package/dist/plugins/directives/transition.js +32 -34
  99. package/dist/plugins/directives/transition.js.map +2 -2
  100. package/dist/plugins/directives/tween.d.ts +2 -2
  101. package/dist/plugins/directives/tween.js +34 -50
  102. package/dist/plugins/directives/tween.js.map +2 -2
  103. package/dist/plugins/directives/two-way-bind.d.ts +1 -1
  104. package/dist/plugins/directives/two-way-bind.js +70 -97
  105. package/dist/plugins/directives/two-way-bind.js.map +2 -2
  106. package/dist/plugins/directives/url-params.js +35 -59
  107. package/dist/plugins/directives/url-params.js.map +3 -3
  108. package/dist/plugins/directives/url-replace.js +6 -7
  109. package/dist/plugins/directives/url-replace.js.map +2 -2
  110. package/dist/plugins/directives/validity.js +6 -9
  111. package/dist/plugins/directives/validity.js.map +2 -2
  112. package/dist/plugins/directives/viewport.js +18 -26
  113. package/dist/plugins/directives/viewport.js.map +2 -2
  114. package/dist/plugins/directives/visibility.js +9 -14
  115. package/dist/plugins/directives/visibility.js.map +2 -2
  116. package/dist/plugins/directives/watch.js +2 -8
  117. package/dist/plugins/directives/watch.js.map +2 -2
  118. package/dist/plugins/functions/bulk-set.js +7 -6
  119. package/dist/plugins/functions/bulk-set.js.map +2 -2
  120. package/dist/plugins/functions/bulk-toggle.js +7 -6
  121. package/dist/plugins/functions/bulk-toggle.js.map +2 -2
  122. package/dist/plugins/functions/confirm.js +2 -2
  123. package/dist/plugins/functions/confirm.js.map +2 -2
  124. package/dist/plugins/functions/copy-text.js +5 -5
  125. package/dist/plugins/functions/copy-text.js.map +2 -2
  126. package/dist/plugins/functions/dispatch.js +5 -5
  127. package/dist/plugins/functions/dispatch.js.map +2 -2
  128. package/dist/plugins/functions/locale-format.d.ts +4 -1
  129. package/dist/plugins/functions/locale-format.js +9 -16
  130. package/dist/plugins/functions/locale-format.js.map +2 -2
  131. package/dist/plugins/functions/range-map.js +6 -6
  132. package/dist/plugins/functions/range-map.js.map +2 -2
  133. package/dist/plugins/functions/request.d.ts +7 -3
  134. package/dist/plugins/functions/request.js +77 -86
  135. package/dist/plugins/functions/request.js.map +2 -2
  136. package/dist/plugins/functions/untracked-read.js +3 -2
  137. package/dist/plugins/functions/untracked-read.js.map +2 -2
  138. package/dist/plugins/functions/websocket.d.ts +3 -3
  139. package/dist/plugins/functions/websocket.js +13 -24
  140. package/dist/plugins/functions/websocket.js.map +2 -2
  141. package/dist/plugins/index.d.ts +0 -2
  142. package/dist/plugins/index.js +0 -4
  143. package/dist/plugins/index.js.map +2 -2
  144. package/dist/plugins/server-events/apply-elements.d.ts +1 -1
  145. package/dist/plugins/server-events/apply-elements.js +41 -43
  146. package/dist/plugins/server-events/apply-elements.js.map +2 -2
  147. package/dist/plugins/server-events/apply-state.js +9 -12
  148. package/dist/plugins/server-events/apply-state.js.map +2 -2
  149. package/dist/plugins/server-events/morph.js +46 -66
  150. package/dist/plugins/server-events/morph.js.map +3 -3
  151. package/dist/presets/all.js +0 -4
  152. package/dist/presets/all.js.map +2 -2
  153. package/dist/server.d.ts +10 -4
  154. package/dist/server.js +42 -14
  155. package/dist/server.js.map +2 -2
  156. package/dist/sigmx.standalone.js +1 -1
  157. package/dist/vite.js +17 -7
  158. package/dist/vite.js.map +2 -2
  159. package/package.json +4 -2
  160. package/dist/plugins/directives/transition-name.d.ts +0 -1
  161. package/dist/plugins/directives/transition-name.js +0 -11
  162. package/dist/plugins/directives/transition-name.js.map +0 -7
  163. package/dist/plugins/directives/trap.d.ts +0 -5
  164. package/dist/plugins/directives/trap.js +0 -54
  165. package/dist/plugins/directives/trap.js.map +0 -7
@@ -1,12 +1,13 @@
1
- import { action, batch, untracked } from "../../kernel/index.js";
2
- const setAll = action({
3
- name: "setAll",
4
- call: ({ store }, value, filter) => batch(
1
+ import { batch, untracked } from "../../kernel/index.js";
2
+ import { act } from "../def.js";
3
+ const setAll = act(
4
+ "setAll",
5
+ ({ store }, value, filter) => batch(
5
6
  () => untracked(() => {
6
- for (const p of store.paths(filter)) store.set(p, value);
7
+ for (const p of store.paths(filter, { computed: false })) store.set(p, value);
7
8
  })
8
9
  )
9
- });
10
+ );
10
11
  export {
11
12
  setAll
12
13
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/bulk-set.ts"],
4
- "sourcesContent": ["import { action, batch, type Filter, untracked } from '../../kernel/index.js';\n\n/** `@setAll(value, { include: /^form\\./ })` assigns every matching signal. */\nexport const setAll = action({\n name: 'setAll',\n call: ({ store }, value: unknown, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter)) store.set(p, value);\n }),\n ),\n});\n"],
5
- "mappings": "AAAA,SAAS,QAAQ,OAAoB,iBAAiB;AAG/C,MAAM,SAAS,OAAO;AAAA,EAC3B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,OAAgB,WAChC;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,KAAK;AAAA,IACzD,CAAC;AAAA,EACH;AACJ,CAAC;",
4
+ "sourcesContent": ["import { batch, type Filter, untracked } from '../../kernel/index.js';\nimport { act } from '../def.js';\n\n/** `@setAll(value, { include: /^form\\./ })` assigns every matching signal. */\nexport const setAll = act('setAll', ({ store }, value: unknown, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter, { computed: false })) store.set(p, value);\n }),\n ),\n);\n"],
5
+ "mappings": "AAAA,SAAS,OAAoB,iBAAiB;AAC9C,SAAS,WAAW;AAGb,MAAM,SAAS;AAAA,EAAI;AAAA,EAAU,CAAC,EAAE,MAAM,GAAG,OAAgB,WAC9D;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,QAAQ,EAAE,UAAU,MAAM,CAAC,EAAG,OAAM,IAAI,GAAG,KAAK;AAAA,IAC9E,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,13 @@
1
- import { action, batch, untracked } from "../../kernel/index.js";
2
- const toggleAll = action({
3
- name: "toggleAll",
4
- call: ({ store }, filter) => batch(
1
+ import { batch, untracked } from "../../kernel/index.js";
2
+ import { act } from "../def.js";
3
+ const toggleAll = act(
4
+ "toggleAll",
5
+ ({ store }, filter) => batch(
5
6
  () => untracked(() => {
6
- for (const p of store.paths(filter)) store.set(p, !store.get(p));
7
+ for (const p of store.paths(filter, { computed: false })) store.set(p, !store.get(p));
7
8
  })
8
9
  )
9
- });
10
+ );
10
11
  export {
11
12
  toggleAll
12
13
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/bulk-toggle.ts"],
4
- "sourcesContent": ["import { action, batch, type Filter, untracked } from '../../kernel/index.js';\n\n/** `@toggleAll({ include: /^flags\\./ })` negates every matching boolean signal. */\nexport const toggleAll = action({\n name: 'toggleAll',\n call: ({ store }, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter)) store.set(p, !store.get(p));\n }),\n ),\n});\n"],
5
- "mappings": "AAAA,SAAS,QAAQ,OAAoB,iBAAiB;AAG/C,MAAM,YAAY,OAAO;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,WAChB;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AACJ,CAAC;",
4
+ "sourcesContent": ["import { batch, type Filter, untracked } from '../../kernel/index.js';\nimport { act } from '../def.js';\n\n/** `@toggleAll({ include: /^flags\\./ })` negates every matching boolean signal. */\nexport const toggleAll = act('toggleAll', ({ store }, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter, { computed: false })) store.set(p, !store.get(p));\n }),\n ),\n);\n"],
5
+ "mappings": "AAAA,SAAS,OAAoB,iBAAiB;AAC9C,SAAS,WAAW;AAGb,MAAM,YAAY;AAAA,EAAI;AAAA,EAAa,CAAC,EAAE,MAAM,GAAG,WACpD;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,QAAQ,EAAE,UAAU,MAAM,CAAC,EAAG,OAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAAA,IACtF,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
- import { action } from "../../kernel/index.js";
2
- const confirm = action({ name: "confirm", call: (_, message) => window.confirm(message) });
1
+ import { act } from "../def.js";
2
+ const confirm = act("confirm", (_, message) => window.confirm(message));
3
3
  export {
4
4
  confirm
5
5
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/confirm.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** `@confirm('Delete?') && @delete('/x')` asks before continuing. */\nexport const confirm = action({ name: 'confirm', call: (_, message: string) => window.confirm(message) });\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,UAAU,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC,GAAG,YAAoB,OAAO,QAAQ,OAAO,EAAE,CAAC;",
4
+ "sourcesContent": ["import { act } from '../def.js';\n\n/** `@confirm('Delete?') && @delete('/x')` asks before continuing. */\nexport const confirm = act('confirm', (_, message: string) => window.confirm(message));\n"],
5
+ "mappings": "AAAA,SAAS,WAAW;AAGb,MAAM,UAAU,IAAI,WAAW,CAAC,GAAG,YAAoB,OAAO,QAAQ,OAAO,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,10 @@
1
- import { action } from "../../kernel/index.js";
2
- const clipboard = action({
3
- name: "clipboard",
4
- call: (_, text, base64 = false) => navigator.clipboard.writeText(
1
+ import { act } from "../def.js";
2
+ const clipboard = act(
3
+ "clipboard",
4
+ (_, text, base64 = false) => navigator.clipboard.writeText(
5
5
  base64 ? new TextDecoder().decode(Uint8Array.from(atob(text), (c) => c.charCodeAt(0))) : text
6
6
  )
7
- });
7
+ );
8
8
  export {
9
9
  clipboard
10
10
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/copy-text.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** `@clipboard(text, isBase64?)` copies text; base64 input is decoded first. */\nexport const clipboard = action({\n name: 'clipboard',\n call: (_, text: string, base64 = false) =>\n navigator.clipboard.writeText(\n base64 ? new TextDecoder().decode(Uint8Array.from(atob(text), (c) => c.charCodeAt(0))) : text,\n ),\n});\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,YAAY,OAAO;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM,CAAC,GAAG,MAAc,SAAS,UAC/B,UAAU,UAAU;AAAA,IAClB,SAAS,IAAI,YAAY,EAAE,OAAO,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI;AAAA,EAC3F;AACJ,CAAC;",
4
+ "sourcesContent": ["import { act } from '../def.js';\n\n/** `@clipboard(text, isBase64?)` copies text; base64 input is decoded first. */\nexport const clipboard = act('clipboard', (_, text: string, base64 = false) =>\n navigator.clipboard.writeText(\n base64 ? new TextDecoder().decode(Uint8Array.from(atob(text), (c) => c.charCodeAt(0))) : text,\n ),\n);\n"],
5
+ "mappings": "AAAA,SAAS,WAAW;AAGb,MAAM,YAAY;AAAA,EAAI;AAAA,EAAa,CAAC,GAAG,MAAc,SAAS,UACnE,UAAU,UAAU;AAAA,IAClB,SAAS,IAAI,YAAY,EAAE,OAAO,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI;AAAA,EAC3F;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- import { action } from "../../kernel/index.js";
2
- const dispatch = action({
3
- name: "dispatch",
4
- call: ({ el }, name, detail) => el.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }))
5
- });
1
+ import { act } from "../def.js";
2
+ const dispatch = act(
3
+ "dispatch",
4
+ ({ el }, name, detail) => el.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }))
5
+ );
6
6
  export {
7
7
  dispatch
8
8
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/dispatch.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** `@dispatch('name', detail)` fires a bubbling CustomEvent from the element. */\nexport const dispatch = action({\n name: 'dispatch',\n call: ({ el }, name: string, detail?: unknown) =>\n el.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true })),\n});\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,WAAW,OAAO;AAAA,EAC7B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,GAAG,GAAG,MAAc,WAC3B,GAAG,cAAc,IAAI,YAAY,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AACrF,CAAC;",
4
+ "sourcesContent": ["import { act } from '../def.js';\n\n/** `@dispatch('name', detail)` fires a bubbling CustomEvent from the element. */\nexport const dispatch = act('dispatch', ({ el }, name: string, detail?: unknown) =>\n el.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true })),\n);\n"],
5
+ "mappings": "AAAA,SAAS,WAAW;AAGb,MAAM,WAAW;AAAA,EAAI;AAAA,EAAY,CAAC,EAAE,GAAG,GAAG,MAAc,WAC7D,GAAG,cAAc,IAAI,YAAY,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AACnF;",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,5 @@
1
- /** `@intl('number', 1234.5, { style: 'currency', currency: 'USD' }, 'en-US')`. */
1
+ /**
2
+ * `@intl('NumberFormat', 1234.5, { style: 'currency', currency: 'EUR' }, 'de')` formats with the named
3
+ * `Intl` API (NumberFormat, DateTimeFormat, PluralRules, RelativeTimeFormat as `[value, unit]`, ListFormat, DisplayNames).
4
+ */
2
5
  export declare const intl: import("../../kernel/contracts.js").ActionPlugin;
@@ -1,20 +1,13 @@
1
- import { action } from "../../kernel/index.js";
2
- const formats = {
3
- number: (l, v, o) => new Intl.NumberFormat(l, o).format(v),
4
- datetime: (l, v, o) => new Intl.DateTimeFormat(l, o).format(v),
5
- pluralRules: (l, v, o) => new Intl.PluralRules(l, o).select(v),
6
- relativeTime: (l, v, o) => new Intl.RelativeTimeFormat(l, o).format(v[0], v[1]),
7
- list: (l, v, o) => new Intl.ListFormat(l, o).format(v),
8
- displayNames: (l, v, o) => new Intl.DisplayNames(l, o).of(v) ?? ""
9
- };
10
- const intl = action({
11
- name: "intl",
12
- call: ({ error }, type, value, options, locale) => {
13
- const f = formats[type];
14
- if (!f) throw error(`unknown @intl type "${type}"`);
15
- return f(locale, value, options);
1
+ import { act } from "../def.js";
2
+ const intl = act(
3
+ "intl",
4
+ ({ error }, type, value, options, locale) => {
5
+ const C = Intl[type];
6
+ if (!C) throw error(`unknown @intl type "${type}"`);
7
+ const f = new C(locale, options);
8
+ return (f.select ?? f.of ?? f.format).call(f, ...type === "RelativeTimeFormat" ? value : [value]) ?? "";
16
9
  }
17
- });
10
+ );
18
11
  export {
19
12
  intl
20
13
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/locale-format.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js';\n\ntype Fmt = (locale: string | string[] | undefined, value: any, options: any) => string;\nconst formats: Record<string, Fmt> = {\n number: (l, v, o) => new Intl.NumberFormat(l, o).format(v),\n datetime: (l, v, o) => new Intl.DateTimeFormat(l, o).format(v),\n pluralRules: (l, v, o) => new Intl.PluralRules(l, o).select(v),\n relativeTime: (l, v, o) => new Intl.RelativeTimeFormat(l, o).format(v[0], v[1]),\n list: (l, v, o) => new Intl.ListFormat(l, o).format(v),\n displayNames: (l, v, o) => new Intl.DisplayNames(l, o).of(v) ?? '',\n};\n\n/** `@intl('number', 1234.5, { style: 'currency', currency: 'USD' }, 'en-US')`. */\nexport const intl = action({\n name: 'intl',\n call: ({ error }, type: string, value: unknown, options?: Record<string, unknown>, locale?: string | string[]) => {\n const f = formats[type];\n if (!f) throw error(`unknown @intl type \"${type}\"`);\n return f(locale, value, options);\n },\n});\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AAGvB,MAAM,UAA+B;AAAA,EACnC,QAAQ,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,aAAa,GAAG,CAAC,EAAE,OAAO,CAAC;AAAA,EACzD,UAAU,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,eAAe,GAAG,CAAC,EAAE,OAAO,CAAC;AAAA,EAC7D,aAAa,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,YAAY,GAAG,CAAC,EAAE,OAAO,CAAC;AAAA,EAC7D,cAAc,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,mBAAmB,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAAA,EAC9E,MAAM,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,WAAW,GAAG,CAAC,EAAE,OAAO,CAAC;AAAA,EACrD,cAAc,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,aAAa,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK;AAClE;AAGO,MAAM,OAAO,OAAO;AAAA,EACzB,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,MAAc,OAAgB,SAAmC,WAA+B;AAChH,UAAM,IAAI,QAAQ,IAAI;AACtB,QAAI,CAAC,EAAG,OAAM,MAAM,uBAAuB,IAAI,GAAG;AAClD,WAAO,EAAE,QAAQ,OAAO,OAAO;AAAA,EACjC;AACF,CAAC;",
4
+ "sourcesContent": ["import { act } from '../def.js';\n\n/**\n * `@intl('NumberFormat', 1234.5, { style: 'currency', currency: 'EUR' }, 'de')` formats with the named\n * `Intl` API (NumberFormat, DateTimeFormat, PluralRules, RelativeTimeFormat as `[value, unit]`, ListFormat, DisplayNames).\n */\nexport const intl = act(\n 'intl',\n ({ error }, type: string, value: any, options?: Record<string, unknown>, locale?: string | string[]) => {\n const C = (Intl as any)[type];\n if (!C) throw error(`unknown @intl type \"${type}\"`);\n const f = new C(locale, options);\n return (f.select ?? f.of ?? f.format).call(f, ...(type === 'RelativeTimeFormat' ? value : [value])) ?? '';\n },\n);\n"],
5
+ "mappings": "AAAA,SAAS,WAAW;AAMb,MAAM,OAAO;AAAA,EAClB;AAAA,EACA,CAAC,EAAE,MAAM,GAAG,MAAc,OAAY,SAAmC,WAA+B;AACtG,UAAM,IAAK,KAAa,IAAI;AAC5B,QAAI,CAAC,EAAG,OAAM,MAAM,uBAAuB,IAAI,GAAG;AAClD,UAAM,IAAI,IAAI,EAAE,QAAQ,OAAO;AAC/B,YAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,KAAK,GAAG,GAAI,SAAS,uBAAuB,QAAQ,CAAC,KAAK,CAAE,KAAK;AAAA,EACzG;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,13 +1,13 @@
1
- import { action } from "../../kernel/index.js";
2
- const fit = action({
3
- name: "fit",
4
- call: (_, v, inMin, inMax, outMin, outMax, clamp = false, round = false) => {
5
- let t = (v - inMin) / (inMax - inMin);
1
+ import { act } from "../def.js";
2
+ const fit = act(
3
+ "fit",
4
+ (_, v, inMin, inMax, outMin, outMax, clamp = false, round = false) => {
5
+ let t = inMax === inMin ? 0 : (v - inMin) / (inMax - inMin);
6
6
  if (clamp) t = Math.min(1, Math.max(0, t));
7
7
  const out = outMin + t * (outMax - outMin);
8
8
  return round ? Math.round(out) : out;
9
9
  }
10
- });
10
+ );
11
11
  export {
12
12
  fit
13
13
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/range-map.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** Map `v` from [inMin, inMax] onto [outMin, outMax]; optionally clamp and round. */\nexport const fit = action({\n name: 'fit',\n call: (_, v: number, inMin: number, inMax: number, outMin: number, outMax: number, clamp = false, round = false) => {\n let t = (v - inMin) / (inMax - inMin);\n if (clamp) t = Math.min(1, Math.max(0, t));\n const out = outMin + t * (outMax - outMin);\n return round ? Math.round(out) : out;\n },\n});\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,MAAM,OAAO;AAAA,EACxB,MAAM;AAAA,EACN,MAAM,CAAC,GAAG,GAAW,OAAe,OAAe,QAAgB,QAAgB,QAAQ,OAAO,QAAQ,UAAU;AAClH,QAAI,KAAK,IAAI,UAAU,QAAQ;AAC/B,QAAI,MAAO,KAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACzC,UAAM,MAAM,SAAS,KAAK,SAAS;AACnC,WAAO,QAAQ,KAAK,MAAM,GAAG,IAAI;AAAA,EACnC;AACF,CAAC;",
4
+ "sourcesContent": ["import { act } from '../def.js';\n\n/** Map `v` from [inMin, inMax] onto [outMin, outMax]; optionally clamp and round. */\nexport const fit = act(\n 'fit',\n (_, v: number, inMin: number, inMax: number, outMin: number, outMax: number, clamp = false, round = false) => {\n let t = inMax === inMin ? 0 : (v - inMin) / (inMax - inMin);\n if (clamp) t = Math.min(1, Math.max(0, t));\n const out = outMin + t * (outMax - outMin);\n return round ? Math.round(out) : out;\n },\n);\n"],
5
+ "mappings": "AAAA,SAAS,WAAW;AAGb,MAAM,MAAM;AAAA,EACjB;AAAA,EACA,CAAC,GAAG,GAAW,OAAe,OAAe,QAAgB,QAAgB,QAAQ,OAAO,QAAQ,UAAU;AAC5G,QAAI,IAAI,UAAU,QAAQ,KAAK,IAAI,UAAU,QAAQ;AACrD,QAAI,MAAO,KAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACzC,UAAM,MAAM,SAAS,KAAK,SAAS;AACnC,WAAO,QAAQ,KAAK,MAAM,GAAG,IAAI;AAAA,EACnC;AACF;",
6
6
  "names": []
7
7
  }
@@ -9,9 +9,7 @@ export type RequestOptions = {
9
9
  /** Explicit body instead of signals. */
10
10
  payload?: unknown;
11
11
  /** 'replace' (default) aborts an earlier request with the same method and URL; 'none' lets them overlap. */
12
- abort?: 'replace' | 'none' | AbortController;
13
- /** Keep the connection open while the tab is hidden. Default: true except for GET streams. */
14
- openWhenHidden?: boolean;
12
+ abort?: 'replace' | 'none';
15
13
  /** Reconnect after a stream closes normally (long-lived event streams). */
16
14
  reconnect?: boolean;
17
15
  retry?: {
@@ -22,6 +20,12 @@ export type RequestOptions = {
22
20
  onStatusError?: boolean;
23
21
  };
24
22
  };
23
+ /** What a request resolves with: the last response that was applied (undefined when nothing was sent). */
24
+ export type RequestResult = {
25
+ url: string;
26
+ status: number;
27
+ redirected: boolean;
28
+ } | undefined;
25
29
  /** `@get(url, options)`: signals travel in the `sigmx` query parameter. */
26
30
  export declare const httpGet: import("../../kernel/contracts.js").ActionPlugin;
27
31
  export declare const httpPost: import("../../kernel/contracts.js").ActionPlugin;
@@ -1,9 +1,11 @@
1
- import { action, untracked } from "../../kernel/index.js";
1
+ import { untracked } from "../../kernel/index.js";
2
2
  import { camel } from "../../lib/casing.js";
3
3
  import { parseFields, readEvents } from "../../lib/sse.js";
4
+ import { act } from "../def.js";
4
5
  const inflight = /* @__PURE__ */ new Map();
5
6
  let seq = 0;
6
7
  const sleep = (ms, signal) => new Promise((resolve) => {
8
+ if (signal.aborted) return resolve();
7
9
  const t = setTimeout(resolve, ms);
8
10
  signal.addEventListener(
9
11
  "abort",
@@ -14,9 +16,6 @@ const sleep = (ms, signal) => new Promise((resolve) => {
14
16
  { once: true }
15
17
  );
16
18
  });
17
- const untilVisible = () => new Promise(
18
- (resolve) => document.addEventListener("visibilitychange", () => !document.hidden && resolve(), { once: true })
19
- );
20
19
  const headerArgs = (res, names, data) => {
21
20
  for (const n of names) {
22
21
  const v = res.headers.get(`sigmx-${n}`);
@@ -24,133 +23,125 @@ const headerArgs = (res, names, data) => {
24
23
  }
25
24
  return data;
26
25
  };
27
- const runScript = (text) => {
28
- const s = document.createElement("script");
29
- s.text = text;
30
- document.head.append(s);
31
- s.remove();
32
- };
33
26
  const send = async (method, ctx, url, o = {}) => {
34
27
  const { el, evt, store, runtime, error } = ctx;
35
28
  if (!url) throw error(`@${method.toLowerCase()} needs a URL`);
36
- const key = `${method} ${url}`;
37
- const ac = o.abort instanceof AbortController ? o.abort : new AbortController();
29
+ const u = new URL(url, location.href);
30
+ const key = `${method} ${u.href}`;
31
+ const hasBody = method !== "GET" && method !== "DELETE";
32
+ const headers = new Headers({ Accept: "text/event-stream, text/html, application/json", "Sigmx-Request": "true" });
33
+ for (const [k, v] of new Headers(o.headers)) headers.set(k, v);
34
+ let body;
35
+ const contentType = (t) => {
36
+ if (hasBody && !headers.has("Content-Type")) headers.set("Content-Type", t);
37
+ };
38
+ if ((o.contentType ?? "json") === "json") {
39
+ const json = JSON.stringify(o.payload ?? untracked(() => store.snapshot(o.filter ?? { exclude: /(^|\.)_/ })));
40
+ if (hasBody) {
41
+ body = json;
42
+ contentType("application/json");
43
+ } else u.searchParams.set("sigmx", json);
44
+ } else {
45
+ const form = o.selector ? document.querySelector(o.selector) : el.closest("form");
46
+ if (!form) throw error("no form found", { selector: o.selector });
47
+ if (!form.noValidate && !form.checkValidity()) {
48
+ form.reportValidity();
49
+ return;
50
+ }
51
+ const submitter = evt instanceof SubmitEvent ? evt.submitter : el instanceof HTMLButtonElement && el.form === form && el.type === "submit" ? el : null;
52
+ const fd = new FormData(form, submitter);
53
+ const params = new URLSearchParams(fd);
54
+ if (!hasBody) for (const [k, v] of params) u.searchParams.append(k, v);
55
+ else if (form.enctype === "multipart/form-data") body = fd;
56
+ else {
57
+ body = params;
58
+ contentType("application/x-www-form-urlencoded");
59
+ }
60
+ }
61
+ const ac = new AbortController();
38
62
  if (o.abort !== "none") {
39
63
  inflight.get(key)?.abort();
40
64
  inflight.set(key, ac);
41
65
  }
42
- ctx.cleanup(() => ac.abort());
66
+ const forget = ctx.cleanup(() => ac.abort());
43
67
  const rid = ++seq;
44
- const emit = (type, extra = {}) => runtime.emit("fetch", { el, type, method, url, rid, ...extra });
45
- const retry = { attempts: 5, interval: 1e3, factor: 2, max: 3e4, onStatusError: false, ...o.retry };
46
- const pauseWhenHidden = !(o.openWhenHidden ?? method !== "GET");
47
- const bodyAllowed = method !== "GET" && method !== "DELETE";
48
- const build = () => {
49
- const u = new URL(url, location.href);
50
- const headers = {
51
- Accept: "text/event-stream, text/html, application/json",
52
- "Sigmx-Request": "true",
53
- ...o.headers
54
- };
55
- let body;
56
- if ((o.contentType ?? "json") === "json") {
57
- const payload = o.payload ?? untracked(() => store.snapshot(o.filter ?? { exclude: /(^|\.)_/ }));
58
- const json = JSON.stringify(payload);
59
- if (bodyAllowed) {
60
- body = json;
61
- headers["Content-Type"] ??= "application/json";
62
- } else u.searchParams.set("sigmx", json);
63
- } else {
64
- const form = o.selector ? document.querySelector(o.selector) : el.closest("form");
65
- if (!form) throw error("no form found", { selector: o.selector });
66
- if (!form.noValidate && !form.checkValidity()) {
67
- form.reportValidity();
68
- return;
69
- }
70
- const submitter = evt instanceof SubmitEvent ? evt.submitter : el instanceof HTMLButtonElement && el.form === form ? el : null;
71
- const fd = new FormData(form, submitter);
72
- const multipart = form.enctype === "multipart/form-data";
73
- if (bodyAllowed) {
74
- body = multipart ? fd : new URLSearchParams(fd);
75
- if (!multipart) headers["Content-Type"] = "application/x-www-form-urlencoded";
76
- } else {
77
- for (const [k, v] of new URLSearchParams(fd)) u.searchParams.append(k, v);
78
- }
79
- }
80
- return { url: u.toString(), init: { method, headers, body } };
81
- };
82
- const route = (event, data) => {
83
- const fields = parseFields(data);
84
- runtime.emit("server-event", { el, event, data: fields });
85
- runtime.handle(event, fields);
86
- };
68
+ const emit = (type, extra) => runtime.emit("fetch", { el, type, method, url, rid, ...extra });
69
+ const retry = { attempts: 5, interval: 1e3, factor: 2, max: 3e4, ...o.retry };
87
70
  let attempt = 0;
88
71
  let wait = retry.interval;
89
72
  let lastId;
73
+ let last;
74
+ let applyError;
75
+ const apply = (fn) => {
76
+ try {
77
+ fn();
78
+ } catch (e) {
79
+ applyError = e;
80
+ throw e;
81
+ }
82
+ };
90
83
  const backoff = async () => {
91
84
  if (attempt++ >= retry.attempts) throw new Error("retries exhausted");
92
- emit("retrying", { attempt });
93
85
  await sleep(wait, ac.signal);
94
86
  wait = Math.min(wait * retry.factor, retry.max);
95
87
  };
96
88
  emit("started");
97
89
  try {
98
90
  while (!ac.signal.aborted) {
99
- const req = build();
100
- if (!req) return;
101
- if (lastId) req.init.headers["Last-Event-ID"] = lastId;
102
- const hide = new AbortController();
103
- const onHide = () => document.hidden && hide.abort();
104
- if (pauseWhenHidden) document.addEventListener("visibilitychange", onHide);
91
+ if (lastId) headers.set("Last-Event-ID", lastId);
105
92
  try {
106
- const res = await fetch(req.url, { ...req.init, signal: AbortSignal.any([ac.signal, hide.signal]) });
93
+ const res = await fetch(u.href, { method, headers, body, signal: ac.signal });
94
+ last = { url: res.url, status: res.status, redirected: res.redirected };
107
95
  const ct = res.headers.get("content-type") ?? "";
108
- if (res.status >= 400) {
96
+ if (!res.ok) {
109
97
  emit("error", { status: res.status });
110
- if (!retry.onStatusError) return;
98
+ if (!retry.onStatusError) return last;
111
99
  await backoff();
112
100
  continue;
113
101
  }
114
- if (res.status === 204 || res.status === 304 || !res.body) return;
102
+ if (!res.body) return last;
115
103
  if (ct.includes("text/event-stream")) {
116
104
  attempt = 0;
117
105
  wait = retry.interval;
118
106
  await readEvents(res.body, (e) => {
119
107
  if (e.id !== void 0) lastId = e.id;
120
108
  if (e.retry) wait = retry.interval = e.retry;
121
- route(e.event, e.data);
109
+ const data = parseFields(e.data);
110
+ apply(() => {
111
+ runtime.emit("server-event", { el, event: e.event, data });
112
+ runtime.handle(e.event, data);
113
+ });
122
114
  });
123
- if (!o.reconnect) return;
115
+ if (!o.reconnect) return last;
124
116
  await backoff();
125
117
  continue;
126
118
  }
127
119
  const text = await res.text();
128
- if (ct.includes("text/html"))
129
- runtime.handle(
130
- "patch-elements",
131
- headerArgs(res, ["selector", "mode", "use-view-transition"], { elements: text })
132
- );
133
- else if (ct.includes("application/json"))
134
- runtime.handle("patch-signals", headerArgs(res, ["only-if-missing"], { signals: text }));
135
- else if (ct.includes("javascript")) runScript(text);
136
- return;
137
- } catch {
138
- if (ac.signal.aborted) return;
139
- if (hide.signal.aborted) await untilVisible();
140
- else await backoff();
141
- } finally {
142
- document.removeEventListener("visibilitychange", onHide);
120
+ apply(() => {
121
+ if (ct.includes("text/html"))
122
+ runtime.handle("patch-elements", headerArgs(res, ["selector", "mode"], { elements: text }));
123
+ else if (ct.includes("application/json"))
124
+ runtime.handle("patch-signals", headerArgs(res, ["only-if-missing"], { signals: text }));
125
+ });
126
+ return last;
127
+ } catch (e) {
128
+ if (ac.signal.aborted) return last;
129
+ if (applyError) throw e;
130
+ await backoff();
143
131
  }
144
132
  }
133
+ return last;
145
134
  } catch (e) {
146
135
  emit("error", { message: e?.message });
147
136
  throw error(`${method} ${url}: ${e?.message ?? e}`);
148
137
  } finally {
149
- emit("finished");
138
+ ac.abort();
139
+ forget();
140
+ emit("finished", last);
150
141
  if (inflight.get(key) === ac) inflight.delete(key);
151
142
  }
152
143
  };
153
- const make = (name, method) => action({ name, call: (ctx, url, o) => send(method, ctx, url, o) });
144
+ const make = (name, method) => act(name, (ctx, url, o) => send(method, ctx, url, o));
154
145
  const httpGet = make("get", "GET");
155
146
  const httpPost = make("post", "POST");
156
147
  const httpPut = make("put", "PUT");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/request.ts"],
4
- "sourcesContent": ["import { type ActionCtx, action, type Filter, untracked } from '../../kernel/index.js';\nimport { camel } from '../../lib/casing.js';\nimport { parseFields, readEvents } from '../../lib/sse.js';\n\nexport type RequestOptions = {\n headers?: Record<string, string>;\n /** 'json' (default) sends filtered signals; 'form' serialises the closest (or `selector`) form. */\n contentType?: 'json' | 'form';\n selector?: string;\n /** Which signals to send. Default: everything except paths starting with `_`. */\n filter?: Filter;\n /** Explicit body instead of signals. */\n payload?: unknown;\n /** 'replace' (default) aborts an earlier request with the same method and URL; 'none' lets them overlap. */\n abort?: 'replace' | 'none' | AbortController;\n /** Keep the connection open while the tab is hidden. Default: true except for GET streams. */\n openWhenHidden?: boolean;\n /** Reconnect after a stream closes normally (long-lived event streams). */\n reconnect?: boolean;\n retry?: { attempts?: number; interval?: number; factor?: number; max?: number; onStatusError?: boolean };\n};\n\nconst inflight = new Map<string, AbortController>();\nlet seq = 0;\nconst sleep = (ms: number, signal: AbortSignal) =>\n new Promise<void>((resolve) => {\n const t = setTimeout(resolve, ms);\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(t);\n resolve();\n },\n { once: true },\n );\n });\nconst untilVisible = () =>\n new Promise<void>((resolve) =>\n document.addEventListener('visibilitychange', () => !document.hidden && resolve(), { once: true }),\n );\n\nconst headerArgs = (res: Response, names: string[], data: Record<string, string>) => {\n for (const n of names) {\n const v = res.headers.get(`sigmx-${n}`);\n if (v) data[camel(n)] = v;\n }\n return data;\n};\n\nconst runScript = (text: string) => {\n const s = document.createElement('script');\n s.text = text;\n document.head.append(s);\n s.remove();\n};\n\nconst send = async (method: string, ctx: ActionCtx, url: string, o: RequestOptions = {}): Promise<void> => {\n const { el, evt, store, runtime, error } = ctx;\n if (!url) throw error(`@${method.toLowerCase()} needs a URL`);\n const key = `${method} ${url}`;\n const ac = o.abort instanceof AbortController ? o.abort : new AbortController();\n if (o.abort !== 'none') {\n inflight.get(key)?.abort();\n inflight.set(key, ac);\n }\n ctx.cleanup(() => ac.abort());\n const rid = ++seq;\n const emit = (type: string, extra: Record<string, unknown> = {}) =>\n runtime.emit('fetch', { el, type, method, url, rid, ...extra });\n const retry = { attempts: 5, interval: 1000, factor: 2, max: 30_000, onStatusError: false, ...o.retry };\n const pauseWhenHidden = !(o.openWhenHidden ?? method !== 'GET');\n const bodyAllowed = method !== 'GET' && method !== 'DELETE';\n\n const build = (): { url: string; init: RequestInit } | undefined => {\n const u = new URL(url, location.href);\n const headers: Record<string, string> = {\n Accept: 'text/event-stream, text/html, application/json',\n 'Sigmx-Request': 'true',\n ...o.headers,\n };\n let body: BodyInit | undefined;\n if ((o.contentType ?? 'json') === 'json') {\n const payload = o.payload ?? untracked(() => store.snapshot(o.filter ?? { exclude: /(^|\\.)_/ }));\n const json = JSON.stringify(payload);\n if (bodyAllowed) {\n body = json;\n headers['Content-Type'] ??= 'application/json';\n } else u.searchParams.set('sigmx', json);\n } else {\n const form = (o.selector ? document.querySelector(o.selector) : el.closest('form')) as HTMLFormElement | null;\n if (!form) throw error('no form found', { selector: o.selector });\n if (!form.noValidate && !form.checkValidity()) {\n form.reportValidity();\n return;\n }\n const submitter =\n evt instanceof SubmitEvent ? evt.submitter : el instanceof HTMLButtonElement && el.form === form ? el : null;\n const fd = new FormData(form, submitter);\n const multipart = form.enctype === 'multipart/form-data';\n if (bodyAllowed) {\n body = multipart ? fd : new URLSearchParams(fd as unknown as Record<string, string>);\n if (!multipart) headers['Content-Type'] = 'application/x-www-form-urlencoded';\n } else {\n for (const [k, v] of new URLSearchParams(fd as unknown as Record<string, string>)) u.searchParams.append(k, v);\n }\n }\n return { url: u.toString(), init: { method, headers, body } };\n };\n\n const route = (event: string, data: string) => {\n const fields = parseFields(data);\n runtime.emit('server-event', { el, event, data: fields });\n runtime.handle(event, fields);\n };\n\n let attempt = 0;\n let wait = retry.interval;\n let lastId: string | undefined;\n const backoff = async () => {\n if (attempt++ >= retry.attempts) throw new Error('retries exhausted');\n emit('retrying', { attempt });\n await sleep(wait, ac.signal);\n wait = Math.min(wait * retry.factor, retry.max);\n };\n\n emit('started');\n try {\n while (!ac.signal.aborted) {\n const req = build();\n if (!req) return;\n if (lastId) (req.init.headers as Record<string, string>)['Last-Event-ID'] = lastId;\n const hide = new AbortController();\n const onHide = () => document.hidden && hide.abort();\n if (pauseWhenHidden) document.addEventListener('visibilitychange', onHide);\n try {\n const res = await fetch(req.url, { ...req.init, signal: AbortSignal.any([ac.signal, hide.signal]) });\n const ct = res.headers.get('content-type') ?? '';\n if (res.status >= 400) {\n emit('error', { status: res.status });\n if (!retry.onStatusError) return;\n await backoff();\n continue;\n }\n if (res.status === 204 || res.status === 304 || !res.body) return;\n if (ct.includes('text/event-stream')) {\n attempt = 0;\n wait = retry.interval;\n await readEvents(res.body, (e) => {\n if (e.id !== undefined) lastId = e.id;\n if (e.retry) wait = retry.interval = e.retry;\n route(e.event, e.data);\n });\n if (!o.reconnect) return;\n await backoff();\n continue;\n }\n const text = await res.text();\n if (ct.includes('text/html'))\n runtime.handle(\n 'patch-elements',\n headerArgs(res, ['selector', 'mode', 'use-view-transition'], { elements: text }),\n );\n else if (ct.includes('application/json'))\n runtime.handle('patch-signals', headerArgs(res, ['only-if-missing'], { signals: text }));\n else if (ct.includes('javascript')) runScript(text);\n return;\n } catch {\n if (ac.signal.aborted) return;\n if (hide.signal.aborted) await untilVisible();\n else await backoff();\n } finally {\n document.removeEventListener('visibilitychange', onHide);\n }\n }\n } catch (e: any) {\n emit('error', { message: e?.message });\n throw error(`${method} ${url}: ${e?.message ?? e}`);\n } finally {\n emit('finished');\n if (inflight.get(key) === ac) inflight.delete(key);\n }\n};\n\nconst make = (name: string, method: string) =>\n action({ name, call: (ctx, url: string, o?: RequestOptions) => send(method, ctx, url, o) });\n\n/** `@get(url, options)`: signals travel in the `sigmx` query parameter. */\nexport const httpGet = make('get', 'GET');\nexport const httpPost = make('post', 'POST');\nexport const httpPut = make('put', 'PUT');\nexport const httpPatch = make('patch', 'PATCH');\nexport const httpDelete = make('delete', 'DELETE');\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { type ActionCtx, type Filter, untracked } from '../../kernel/index.js';\nimport { camel } from '../../lib/casing.js';\nimport { parseFields, readEvents } from '../../lib/sse.js';\nimport { act } from '../def.js';\n\nexport type RequestOptions = {\n headers?: Record<string, string>;\n /** 'json' (default) sends filtered signals; 'form' serialises the closest (or `selector`) form. */\n contentType?: 'json' | 'form';\n selector?: string;\n /** Which signals to send. Default: everything except paths starting with `_`. */\n filter?: Filter;\n /** Explicit body instead of signals. */\n payload?: unknown;\n /** 'replace' (default) aborts an earlier request with the same method and URL; 'none' lets them overlap. */\n abort?: 'replace' | 'none';\n /** Reconnect after a stream closes normally (long-lived event streams). */\n reconnect?: boolean;\n retry?: { attempts?: number; interval?: number; factor?: number; max?: number; onStatusError?: boolean };\n};\n\n/** What a request resolves with: the last response that was applied (undefined when nothing was sent). */\nexport type RequestResult = { url: string; status: number; redirected: boolean } | undefined;\n\nconst inflight = new Map<string, AbortController>();\nlet seq = 0;\nconst sleep = (ms: number, signal: AbortSignal) =>\n new Promise<void>((resolve) => {\n if (signal.aborted) return resolve();\n const t = setTimeout(resolve, ms);\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(t);\n resolve();\n },\n { once: true },\n );\n });\n\n/** Response headers `sigmx-<name>` become camel-cased fields of `data`. */\nconst headerArgs = (res: Response, names: string[], data: Record<string, string>) => {\n for (const n of names) {\n const v = res.headers.get(`sigmx-${n}`);\n if (v) data[camel(n)] = v;\n }\n return data;\n};\n\nconst send = async (method: string, ctx: ActionCtx, url: string, o: RequestOptions = {}): Promise<RequestResult> => {\n const { el, evt, store, runtime, error } = ctx;\n if (!url) throw error(`@${method.toLowerCase()} needs a URL`);\n const u = new URL(url, location.href);\n const key = `${method} ${u.href}`; // resolved, before any signals are appended\n const hasBody = method !== 'GET' && method !== 'DELETE';\n const headers = new Headers({ Accept: 'text/event-stream, text/html, application/json', 'Sigmx-Request': 'true' });\n for (const [k, v] of new Headers(o.headers)) headers.set(k, v);\n let body: BodyInit | undefined;\n const contentType = (t: string) => {\n if (hasBody && !headers.has('Content-Type')) headers.set('Content-Type', t);\n };\n if ((o.contentType ?? 'json') === 'json') {\n const json = JSON.stringify(o.payload ?? untracked(() => store.snapshot(o.filter ?? { exclude: /(^|\\.)_/ })));\n if (hasBody) {\n body = json;\n contentType('application/json');\n } else u.searchParams.set('sigmx', json);\n } else {\n const form = (o.selector ? document.querySelector(o.selector) : el.closest('form')) as HTMLFormElement | null;\n if (!form) throw error('no form found', { selector: o.selector });\n if (!form.noValidate && !form.checkValidity()) {\n form.reportValidity();\n return;\n }\n // Only a real submit button may be the submitter; FormData throws for anything else.\n const submitter =\n evt instanceof SubmitEvent\n ? evt.submitter\n : el instanceof HTMLButtonElement && el.form === form && el.type === 'submit'\n ? el\n : null;\n const fd = new FormData(form, submitter);\n const params = new URLSearchParams(fd as unknown as Record<string, string>);\n if (!hasBody) for (const [k, v] of params) u.searchParams.append(k, v);\n else if (form.enctype === 'multipart/form-data') body = fd;\n else {\n body = params;\n contentType('application/x-www-form-urlencoded');\n }\n }\n\n const ac = new AbortController();\n if (o.abort !== 'none') {\n inflight.get(key)?.abort();\n inflight.set(key, ac);\n }\n const forget = ctx.cleanup(() => ac.abort());\n const rid = ++seq;\n const emit = (type: string, extra?: object) => runtime.emit('fetch', { el, type, method, url, rid, ...extra });\n const retry = { attempts: 5, interval: 1000, factor: 2, max: 30_000, ...o.retry };\n let attempt = 0;\n let wait = retry.interval;\n let lastId: string | undefined;\n let last: RequestResult;\n // Exceptions thrown while applying a response are the page's problem, not the network's: no retry.\n let applyError: unknown;\n const apply = (fn: () => void) => {\n try {\n fn();\n } catch (e) {\n applyError = e;\n throw e;\n }\n };\n const backoff = async () => {\n if (attempt++ >= retry.attempts) throw new Error('retries exhausted');\n await sleep(wait, ac.signal);\n wait = Math.min(wait * retry.factor, retry.max);\n };\n\n emit('started');\n try {\n while (!ac.signal.aborted) {\n if (lastId) headers.set('Last-Event-ID', lastId);\n try {\n const res = await fetch(u.href, { method, headers, body, signal: ac.signal });\n last = { url: res.url, status: res.status, redirected: res.redirected };\n const ct = res.headers.get('content-type') ?? '';\n if (!res.ok) {\n emit('error', { status: res.status });\n if (!retry.onStatusError) return last;\n await backoff();\n continue;\n }\n if (!res.body) return last;\n if (ct.includes('text/event-stream')) {\n attempt = 0;\n wait = retry.interval;\n await readEvents(res.body, (e) => {\n if (e.id !== undefined) lastId = e.id;\n if (e.retry) wait = retry.interval = e.retry;\n const data = parseFields(e.data);\n apply(() => {\n runtime.emit('server-event', { el, event: e.event, data });\n runtime.handle(e.event, data);\n });\n });\n if (!o.reconnect) return last;\n await backoff();\n continue;\n }\n const text = await res.text();\n apply(() => {\n if (ct.includes('text/html'))\n runtime.handle('patch-elements', headerArgs(res, ['selector', 'mode'], { elements: text }));\n else if (ct.includes('application/json'))\n runtime.handle('patch-signals', headerArgs(res, ['only-if-missing'], { signals: text }));\n });\n return last;\n } catch (e) {\n if (ac.signal.aborted) return last;\n if (applyError) throw e;\n await backoff();\n }\n }\n return last;\n } catch (e: any) {\n emit('error', { message: e?.message });\n throw error(`${method} ${url}: ${e?.message ?? e}`);\n } finally {\n ac.abort(); // releases a still-open body and any pending backoff\n forget();\n emit('finished', last);\n if (inflight.get(key) === ac) inflight.delete(key);\n }\n};\n\nconst make = (name: string, method: string) =>\n act(name, (ctx, url: string, o?: RequestOptions) => send(method, ctx, url, o));\n\n/** `@get(url, options)`: signals travel in the `sigmx` query parameter. */\nexport const httpGet = make('get', 'GET');\nexport const httpPost = make('post', 'POST');\nexport const httpPut = make('put', 'PUT');\nexport const httpPatch = make('patch', 'PATCH');\nexport const httpDelete = make('delete', 'DELETE');\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
- import { action, untracked } from "../../kernel/index.js";
2
- const peek = action({ name: "peek", call: (_, fn) => untracked(fn) });
1
+ import { untracked } from "../../kernel/index.js";
2
+ import { act } from "../def.js";
3
+ const peek = act("peek", (_, fn) => typeof fn === "function" ? untracked(fn) : fn);
3
4
  export {
4
5
  peek
5
6
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/untracked-read.ts"],
4
- "sourcesContent": ["import { action, untracked } from '../../kernel/index.js';\n\n/** `@peek(() => $x)` reads signals without subscribing the surrounding effect. */\nexport const peek = action({ name: 'peek', call: (_, fn: () => unknown) => untracked(fn) });\n"],
5
- "mappings": "AAAA,SAAS,QAAQ,iBAAiB;AAG3B,MAAM,OAAO,OAAO,EAAE,MAAM,QAAQ,MAAM,CAAC,GAAG,OAAsB,UAAU,EAAE,EAAE,CAAC;",
4
+ "sourcesContent": ["import { untracked } from '../../kernel/index.js';\nimport { act } from '../def.js';\n\n/** `@peek(() => $x)` reads signals without subscribing the surrounding effect. */\nexport const peek = act('peek', (_, fn: unknown) => (typeof fn === 'function' ? untracked(fn as () => unknown) : fn));\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAC1B,SAAS,WAAW;AAGb,MAAM,OAAO,IAAI,QAAQ,CAAC,GAAG,OAAiB,OAAO,OAAO,aAAa,UAAU,EAAmB,IAAI,EAAG;",
6
6
  "names": []
7
7
  }
@@ -4,8 +4,8 @@ export type Socket = {
4
4
  readonly socket: WebSocket;
5
5
  };
6
6
  /**
7
- * `@ws('/live')` opens a WebSocket and routes incoming messages like a server event stream: text
8
- * blocks of `event: name` and `data: key value` lines, separated by blank lines. Returns
9
- * `{ send, close, socket }`; `send` JSON-encodes objects. The socket closes when the element unmounts.
7
+ * `@ws(url, { protocols })` opens a WebSocket whose messages use the server-event wire format
8
+ * (`event <name>` and `data <key> <value>` lines, blank-line separated) and routes them to the
9
+ * same handlers as fetched streams. Returns `{ send, close, socket }`; closed when the element unmounts.
10
10
  */
11
11
  export declare const websocket: import("../../kernel/contracts.js").ActionPlugin;