@madojs/mado 0.11.1 → 0.13.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 (298) hide show
  1. package/AGENTS.md +116 -32
  2. package/CHANGELOG.md +216 -1
  3. package/README.md +158 -173
  4. package/dist/src/component.d.ts +6 -3
  5. package/dist/src/component.d.ts.map +1 -0
  6. package/dist/src/component.js +163 -36
  7. package/dist/src/component.js.map +1 -1
  8. package/dist/src/context.d.ts +13 -32
  9. package/dist/src/context.d.ts.map +1 -0
  10. package/dist/src/context.js +73 -48
  11. package/dist/src/context.js.map +1 -1
  12. package/dist/src/css.d.ts +1 -0
  13. package/dist/src/css.d.ts.map +1 -0
  14. package/dist/src/css.js +34 -5
  15. package/dist/src/css.js.map +1 -1
  16. package/dist/src/devtools-hook.d.ts +14 -0
  17. package/dist/src/devtools-hook.d.ts.map +1 -0
  18. package/dist/src/devtools-hook.js +27 -0
  19. package/dist/src/devtools-hook.js.map +1 -0
  20. package/dist/src/devtools.d.ts +24 -22
  21. package/dist/src/devtools.d.ts.map +1 -0
  22. package/dist/src/devtools.js +230 -58
  23. package/dist/src/devtools.js.map +1 -1
  24. package/dist/src/diagnostics.d.ts +12 -0
  25. package/dist/src/diagnostics.d.ts.map +1 -0
  26. package/dist/src/diagnostics.js +68 -8
  27. package/dist/src/diagnostics.js.map +1 -1
  28. package/dist/src/each.d.ts +1 -5
  29. package/dist/src/each.d.ts.map +1 -0
  30. package/dist/src/each.js +0 -8
  31. package/dist/src/each.js.map +1 -1
  32. package/dist/src/forms.d.ts +27 -96
  33. package/dist/src/forms.d.ts.map +1 -0
  34. package/dist/src/forms.js +184 -394
  35. package/dist/src/forms.js.map +1 -1
  36. package/dist/src/head.d.ts +7 -6
  37. package/dist/src/head.d.ts.map +1 -0
  38. package/dist/src/head.js +8 -7
  39. package/dist/src/head.js.map +1 -1
  40. package/dist/src/html/bindings.d.ts +1 -0
  41. package/dist/src/html/bindings.d.ts.map +1 -0
  42. package/dist/src/html/bindings.js.map +1 -1
  43. package/dist/src/html/parser.d.ts +4 -5
  44. package/dist/src/html/parser.d.ts.map +1 -0
  45. package/dist/src/html/parser.js +64 -15
  46. package/dist/src/html/parser.js.map +1 -1
  47. package/dist/src/html/template-types.d.ts +1 -0
  48. package/dist/src/html/template-types.d.ts.map +1 -0
  49. package/dist/src/html/template-types.js.map +1 -1
  50. package/dist/src/html/template.d.ts +5 -1
  51. package/dist/src/html/template.d.ts.map +1 -0
  52. package/dist/src/html/template.js +102 -13
  53. package/dist/src/html/template.js.map +1 -1
  54. package/dist/src/index.d.ts +15 -12
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +18 -10
  57. package/dist/src/index.js.map +1 -1
  58. package/dist/src/json.d.ts +3 -0
  59. package/dist/src/json.d.ts.map +1 -0
  60. package/dist/src/json.js +14 -0
  61. package/dist/src/json.js.map +1 -0
  62. package/dist/src/lifecycle.d.ts +1 -0
  63. package/dist/src/lifecycle.d.ts.map +1 -0
  64. package/dist/src/lifecycle.js +3 -2
  65. package/dist/src/lifecycle.js.map +1 -1
  66. package/dist/src/page.d.ts +63 -28
  67. package/dist/src/page.d.ts.map +1 -0
  68. package/dist/src/page.js +5 -0
  69. package/dist/src/page.js.map +1 -1
  70. package/dist/src/persisted.d.ts +6 -1
  71. package/dist/src/persisted.d.ts.map +1 -0
  72. package/dist/src/persisted.js +17 -11
  73. package/dist/src/persisted.js.map +1 -1
  74. package/dist/src/resource.d.ts +2 -1
  75. package/dist/src/resource.d.ts.map +1 -0
  76. package/dist/src/resource.js +128 -50
  77. package/dist/src/resource.js.map +1 -1
  78. package/dist/src/router/base.d.ts +66 -0
  79. package/dist/src/router/base.d.ts.map +1 -0
  80. package/dist/src/router/base.js +168 -0
  81. package/dist/src/router/base.js.map +1 -0
  82. package/dist/src/router/manifest.d.ts +1 -0
  83. package/dist/src/router/manifest.d.ts.map +1 -0
  84. package/dist/src/router/manifest.js +156 -171
  85. package/dist/src/router/manifest.js.map +1 -1
  86. package/dist/src/router/match.d.ts +17 -2
  87. package/dist/src/router/match.d.ts.map +1 -0
  88. package/dist/src/router/match.js +60 -6
  89. package/dist/src/router/match.js.map +1 -1
  90. package/dist/src/router/navigation.d.ts +1 -0
  91. package/dist/src/router/navigation.d.ts.map +1 -0
  92. package/dist/src/router/navigation.js +58 -9
  93. package/dist/src/router/navigation.js.map +1 -1
  94. package/dist/src/signal.d.ts +1 -0
  95. package/dist/src/signal.d.ts.map +1 -0
  96. package/dist/src/signal.js +46 -17
  97. package/dist/src/signal.js.map +1 -1
  98. package/dist/src/static-runtime.d.ts +82 -0
  99. package/dist/src/static-runtime.d.ts.map +1 -0
  100. package/dist/src/static-runtime.js +209 -0
  101. package/dist/src/static-runtime.js.map +1 -0
  102. package/dist/src/vite/index.d.ts +32 -3
  103. package/dist/src/vite/index.d.ts.map +1 -0
  104. package/dist/src/vite/index.js +49 -17
  105. package/dist/src/vite/index.js.map +1 -1
  106. package/docs/README.md +5 -8
  107. package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
  108. package/docs/architecture/v1-roadmap.md +19 -0
  109. package/docs/en/00-the-mado-way.md +1 -1
  110. package/docs/en/01-quickstart.md +183 -0
  111. package/docs/en/10-pages-and-components.md +279 -0
  112. package/docs/en/11-templates-and-signals.md +211 -0
  113. package/docs/en/12-routing.md +229 -0
  114. package/docs/en/13-data.md +227 -0
  115. package/docs/en/14-forms.md +91 -0
  116. package/docs/en/15-static-snapshots.md +181 -0
  117. package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +56 -4
  118. package/docs/en/{13-deployment.md → 20-deployment.md} +79 -17
  119. package/docs/en/{15-error-handling.md → 21-error-handling.md} +9 -6
  120. package/docs/en/{14-testing.md → 22-testing.md} +6 -5
  121. package/docs/en/23-cookbook.md +292 -0
  122. package/docs/en/24-devtools-and-diagnostics.md +45 -0
  123. package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +17 -9
  124. package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +5 -5
  125. package/docs/en/33-migration-0.12-0.13.md +56 -0
  126. package/docs/en/40-llm-guide.md +774 -0
  127. package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +28 -25
  128. package/docs/en/{05-why-mado.md → 42-why-mado.md} +3 -3
  129. package/docs/en/README.md +99 -27
  130. package/docs/recipes/nginx/Containerfile +26 -0
  131. package/docs/recipes/nginx/nginx.conf +42 -0
  132. package/llms.txt +263 -210
  133. package/package.json +51 -23
  134. package/scripts/clean.mjs +8 -0
  135. package/scripts/cli/generate.mjs +57 -10
  136. package/scripts/cli/help.mjs +13 -5
  137. package/scripts/cli/index.mjs +31 -7
  138. package/scripts/cli/init.mjs +19 -19
  139. package/scripts/cli/release.mjs +38 -83
  140. package/scripts/cli/run.mjs +5 -3
  141. package/scripts/logger.mjs +117 -0
  142. package/scripts/output-guard.mjs +128 -0
  143. package/scripts/preview.mjs +105 -24
  144. package/scripts/static/browser.mjs +695 -0
  145. package/scripts/static/discover.mjs +284 -0
  146. package/scripts/static/output.mjs +141 -0
  147. package/scripts/static/serialize.mjs +212 -0
  148. package/scripts/static/server.mjs +167 -0
  149. package/scripts/static.mjs +205 -0
  150. package/starters/default/README.md +57 -55
  151. package/starters/default/package.json +6 -12
  152. package/starters/default/src/app.routes.ts +20 -33
  153. package/starters/default/src/components/feature-card.component.ts +40 -0
  154. package/starters/default/src/components/live-counter.component.ts +57 -0
  155. package/starters/default/src/content/guides.ts +55 -0
  156. package/starters/default/src/main.ts +9 -13
  157. package/starters/default/src/pages/app.page.ts +41 -0
  158. package/starters/default/src/pages/guide.page.ts +40 -0
  159. package/starters/default/src/pages/home.page.ts +49 -0
  160. package/starters/default/src/pages/not-found.page.ts +18 -0
  161. package/starters/default/src/styles/document.css +39 -0
  162. package/starters/default/src/styles/reset.css +37 -0
  163. package/starters/default/src/styles/tokens.css +30 -0
  164. package/starters/default/src/styles.d.ts +3 -1
  165. package/starters/default/src/vite-env.d.ts +1 -1
  166. package/starters/default/tsconfig.node.json +13 -0
  167. package/starters/default/vite.config.ts +14 -4
  168. package/starters/modular/README.md +142 -0
  169. package/starters/modular/index.html +13 -0
  170. package/starters/modular/package.json +30 -0
  171. package/starters/modular/src/app.routes.ts +39 -0
  172. package/starters/{default → modular}/src/layouts/app-shell.layout.ts +9 -7
  173. package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
  174. package/starters/modular/src/main.ts +16 -0
  175. package/starters/{default → modular}/src/modules/auth/login.page.ts +5 -12
  176. package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +3 -4
  177. package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +4 -4
  178. package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
  179. package/starters/modular/src/modules/home/not-found.page.ts +14 -0
  180. package/starters/{default → modular}/src/shared/styles/reset.css +21 -1
  181. package/starters/modular/src/styles.d.ts +1 -0
  182. package/starters/modular/src/vite-env.d.ts +1 -0
  183. package/starters/modular/tsconfig.json +33 -0
  184. package/starters/modular/tsconfig.node.json +13 -0
  185. package/starters/modular/vite.config.ts +132 -0
  186. package/TODO.md +0 -79
  187. package/dist/src/lazy.d.ts +0 -38
  188. package/dist/src/lazy.js +0 -73
  189. package/dist/src/lazy.js.map +0 -1
  190. package/docs/en/01-routing.md +0 -152
  191. package/docs/en/02-project-layout.md +0 -124
  192. package/docs/en/03-static-bake.md +0 -249
  193. package/docs/en/04-ide-setup.md +0 -162
  194. package/docs/en/07-llm-pitfalls.md +0 -724
  195. package/docs/en/08-llm-zero-history-test.md +0 -56
  196. package/docs/en/09-shadow-vs-light-dom.md +0 -174
  197. package/docs/en/11-layouts.md +0 -113
  198. package/docs/en/12-auth-and-api.md +0 -124
  199. package/docs/en/16-bake-cookbook.md +0 -100
  200. package/docs/en/17-shadow-dom-forms.md +0 -192
  201. package/docs/fr/00-the-mado-way.md +0 -85
  202. package/docs/fr/01-routing.md +0 -120
  203. package/docs/fr/02-project-layout.md +0 -84
  204. package/docs/fr/03-static-bake.md +0 -289
  205. package/docs/fr/04-ide-setup.md +0 -162
  206. package/docs/fr/05-why-mado.md +0 -193
  207. package/docs/fr/06-for-backenders.md +0 -438
  208. package/docs/fr/07-llm-pitfalls.md +0 -625
  209. package/docs/fr/08-llm-zero-history-test.md +0 -38
  210. package/docs/fr/09-shadow-vs-light-dom.md +0 -65
  211. package/docs/fr/10-app-architecture.md +0 -138
  212. package/docs/fr/11-layouts.md +0 -47
  213. package/docs/fr/12-auth-and-api.md +0 -76
  214. package/docs/fr/13-deployment.md +0 -57
  215. package/docs/fr/14-testing.md +0 -41
  216. package/docs/fr/15-error-handling.md +0 -50
  217. package/docs/fr/16-bake-cookbook.md +0 -88
  218. package/docs/fr/17-shadow-dom-forms.md +0 -196
  219. package/docs/fr/18-api-freeze-map.md +0 -63
  220. package/docs/fr/19-reactivity-ordering.md +0 -97
  221. package/docs/fr/20-v1-stability.md +0 -88
  222. package/docs/fr/README.md +0 -27
  223. package/docs/ru/00-the-mado-way.md +0 -84
  224. package/docs/ru/01-routing.md +0 -119
  225. package/docs/ru/02-project-layout.md +0 -84
  226. package/docs/ru/03-static-bake.md +0 -250
  227. package/docs/ru/04-ide-setup.md +0 -144
  228. package/docs/ru/05-why-mado.md +0 -193
  229. package/docs/ru/06-for-backenders.md +0 -428
  230. package/docs/ru/07-llm-pitfalls.md +0 -624
  231. package/docs/ru/08-llm-zero-history-test.md +0 -57
  232. package/docs/ru/09-shadow-vs-light-dom.md +0 -63
  233. package/docs/ru/10-app-architecture.md +0 -152
  234. package/docs/ru/11-layouts.md +0 -47
  235. package/docs/ru/12-auth-and-api.md +0 -75
  236. package/docs/ru/13-deployment.md +0 -66
  237. package/docs/ru/14-testing.md +0 -50
  238. package/docs/ru/15-error-handling.md +0 -56
  239. package/docs/ru/16-bake-cookbook.md +0 -95
  240. package/docs/ru/17-shadow-dom-forms.md +0 -193
  241. package/docs/ru/18-api-freeze-map.md +0 -64
  242. package/docs/ru/19-reactivity-ordering.md +0 -95
  243. package/docs/ru/20-v1-stability.md +0 -82
  244. package/docs/ru/README.md +0 -25
  245. package/docs/uk/00-the-mado-way.md +0 -82
  246. package/docs/uk/01-routing.md +0 -76
  247. package/docs/uk/02-project-layout.md +0 -73
  248. package/docs/uk/03-static-bake.md +0 -48
  249. package/docs/uk/04-ide-setup.md +0 -26
  250. package/docs/uk/05-why-mado.md +0 -34
  251. package/docs/uk/06-for-backenders.md +0 -55
  252. package/docs/uk/07-llm-pitfalls.md +0 -145
  253. package/docs/uk/08-llm-zero-history-test.md +0 -34
  254. package/docs/uk/09-shadow-vs-light-dom.md +0 -58
  255. package/docs/uk/10-app-architecture.md +0 -97
  256. package/docs/uk/11-layouts.md +0 -47
  257. package/docs/uk/12-auth-and-api.md +0 -70
  258. package/docs/uk/13-deployment.md +0 -40
  259. package/docs/uk/14-testing.md +0 -34
  260. package/docs/uk/15-error-handling.md +0 -32
  261. package/docs/uk/16-bake-cookbook.md +0 -36
  262. package/docs/uk/17-shadow-dom-forms.md +0 -193
  263. package/docs/uk/18-api-freeze-map.md +0 -61
  264. package/docs/uk/19-reactivity-ordering.md +0 -95
  265. package/docs/uk/20-v1-stability.md +0 -83
  266. package/docs/uk/README.md +0 -27
  267. package/scripts/bake.mjs +0 -570
  268. package/scripts/package-smoke.mjs +0 -77
  269. package/scripts/release-notes.mjs +0 -66
  270. package/scripts/size-budget.mjs +0 -91
  271. package/starters/default/src/modules/home/not-found.page.ts +0 -11
  272. package/starters/default/src/shared/ui/x-button.component.ts +0 -49
  273. /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
  274. /package/starters/{default → modular}/.editorconfig +0 -0
  275. /package/starters/{default → modular}/eslint.config.mjs +0 -0
  276. /package/starters/{default → modular}/public/favicon.svg +0 -0
  277. /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
  278. /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
  279. /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
  280. /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
  281. /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
  282. /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
  283. /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
  284. /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
  285. /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
  286. /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
  287. /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
  288. /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
  289. /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
  290. /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
  291. /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
  292. /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
  293. /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
  294. /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
  295. /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
  296. /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
  297. /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
  298. /package/starters/{default → modular}/src/shared/ui/x-spinner.component.ts +0 -0
@@ -17,9 +17,10 @@
17
17
  */
18
18
  import { signal, effect, untracked } from "./signal.js";
19
19
  import { getCurrentLifecycle } from "./lifecycle.js";
20
- import { warnOnce } from "./diagnostics.js";
21
- const cache = new Map();
22
- const inFlight = new Map();
20
+ import { reportError, warnOnce } from "./diagnostics.js";
21
+ import { trackStatic } from "./static-runtime.js";
22
+ import { emitDevtools } from "./devtools-hook.js";
23
+ const fetcherStates = new Map();
23
24
  const invalidators = new Set();
24
25
  /**
25
26
  * Remove from cache all keys matching the pattern, and force
@@ -35,26 +36,29 @@ const invalidators = new Set();
35
36
  * or iterate your own keys manually.
36
37
  */
37
38
  export function invalidate(pattern) {
38
- const isGlob = pattern.endsWith("*");
39
- const prefix = isGlob ? pattern.slice(0, -1) : pattern;
40
- const toDelete = [];
41
- for (const key of cache.keys()) {
42
- if (isGlob ? key.startsWith(prefix) : key === pattern) {
43
- toDelete.push(key);
39
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
40
+ emitDevtools("resource:invalidate", undefined, { pattern });
41
+ for (const [fetcher, state] of fetcherStates) {
42
+ for (const [key, entry] of state.cache) {
43
+ if (matchesPattern(key, pattern)) {
44
+ if (entry.expires)
45
+ clearTimeout(entry.expires);
46
+ state.cache.delete(key);
47
+ }
44
48
  }
49
+ releaseFetcherState(fetcher, state);
45
50
  }
46
- for (const k of toDelete)
47
- cache.delete(k);
48
- for (const fn of invalidators) {
49
- for (const k of toDelete)
50
- fn(k);
51
- }
51
+ for (const fn of invalidators)
52
+ fn(pattern);
52
53
  }
53
54
  export function resource(keyFn, fetcher, options = {}) {
54
55
  const data = signal(options.initialData);
55
56
  const error = signal(null);
56
57
  const loading = signal(false);
57
58
  const keySig = signal("");
59
+ const debugTarget = {};
60
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
61
+ emitDevtools("resource:create", debugTarget);
58
62
  let releaseInFlight = null;
59
63
  let requestSeq = 0;
60
64
  let lastKey = "";
@@ -73,15 +77,20 @@ export function resource(keyFn, fetcher, options = {}) {
73
77
  releaseInFlight?.();
74
78
  releaseInFlight = null;
75
79
  const seq = ++requestSeq;
80
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
81
+ emitDevtools("resource:request", debugTarget, { key, seq, force });
76
82
  // if there is a fresh cache and not forced — use it
77
- const cached = cache.get(key);
83
+ const cached = getFetcherState(fetcher).cache.get(key);
78
84
  if (cached &&
79
85
  !force &&
80
- (!options.staleTime || Date.now() - cached.timestamp < options.staleTime)) {
86
+ (options.staleTime === Infinity ||
87
+ Date.now() - cached.timestamp < (options.staleTime ?? 0))) {
81
88
  data.set(cached.data);
82
89
  error.set(null);
83
90
  loading.set(false);
84
- return;
91
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
92
+ emitDevtools("resource:cache-hit", debugTarget, { key });
93
+ return Promise.resolve(cached.data);
85
94
  }
86
95
  loading.set(true);
87
96
  error.set(null);
@@ -100,9 +109,11 @@ export function resource(keyFn, fetcher, options = {}) {
100
109
  return;
101
110
  if (key !== lastKey)
102
111
  return;
103
- cache.set(key, { data: result, timestamp: Date.now() });
112
+ writeCache(fetcher, key, result, options.staleTime ?? 0);
104
113
  data.set(result);
105
114
  loading.set(false);
115
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
116
+ emitDevtools("resource:success", debugTarget, { key, seq, result });
106
117
  }, (err) => {
107
118
  retained.release();
108
119
  if (seq !== requestSeq)
@@ -111,7 +122,10 @@ export function resource(keyFn, fetcher, options = {}) {
111
122
  return;
112
123
  error.set(err instanceof Error ? err : new Error(String(err)));
113
124
  loading.set(false);
125
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
126
+ emitDevtools("resource:error", debugTarget, { key, seq, error: err });
114
127
  });
128
+ return retained.promise;
115
129
  };
116
130
  // subscribe to key changes
117
131
  const stopKeyEffect = effect(() => {
@@ -119,14 +133,14 @@ export function resource(keyFn, fetcher, options = {}) {
119
133
  keySig.set(key);
120
134
  if (key !== lastKey || force) {
121
135
  lastKey = key;
122
- run(key);
136
+ void run(key);
123
137
  }
124
138
  });
125
139
  // subscribe to global invalidation
126
- const onInv = (invKey) => {
127
- if (invKey === lastKey) {
140
+ const onInv = (pattern) => {
141
+ if (matchesPattern(lastKey, pattern)) {
128
142
  force = true;
129
- run(lastKey);
143
+ void run(lastKey);
130
144
  }
131
145
  };
132
146
  invalidators.add(onInv);
@@ -138,6 +152,8 @@ export function resource(keyFn, fetcher, options = {}) {
138
152
  invalidators.delete(onInv);
139
153
  releaseInFlight?.();
140
154
  releaseInFlight = null;
155
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
156
+ emitDevtools("resource:dispose", debugTarget, { key: lastKey });
141
157
  });
142
158
  }
143
159
  return {
@@ -149,7 +165,9 @@ export function resource(keyFn, fetcher, options = {}) {
149
165
  force = true;
150
166
  // read key without tracking — otherwise we'd end up inside someone else's effect
151
167
  const key = untracked(keyFn);
152
- run(key);
168
+ lastKey = key;
169
+ keySig.set(key);
170
+ return run(key);
153
171
  },
154
172
  mutate(next) {
155
173
  const prev = data.peek();
@@ -158,33 +176,30 @@ export function resource(keyFn, fetcher, options = {}) {
158
176
  : next;
159
177
  data.set(value);
160
178
  if (lastKey)
161
- cache.set(lastKey, { data: value, timestamp: Date.now() });
179
+ writeCache(fetcher, lastKey, value, options.staleTime ?? 0);
162
180
  },
163
181
  };
164
182
  }
165
183
  function retainInFlight(key, fetcher, force) {
166
- let entry = (!force ? inFlight.get(key) : undefined);
167
- if (entry && entry.fetcher !== fetcher) {
168
- warnOnce(`resource-key-collision-${key}`, `resource key collision for "${key}": multiple in-flight ` +
169
- "resource() calls use different fetchers. Resource keys must uniquely " +
170
- "identify both the endpoint and the data shape.");
171
- }
184
+ const state = getFetcherState(fetcher);
185
+ let entry = (!force ? state.inFlight.get(key) : undefined);
172
186
  if (!entry) {
173
187
  const controller = new AbortController();
174
188
  entry = {
175
189
  controller,
176
- fetcher,
177
190
  consumers: 0,
178
- promise: fetcher(key, controller.signal),
191
+ promise: trackStatic(fetcher(key, controller.signal), `resource ${key}`),
179
192
  };
180
193
  entry.promise.then(() => {
181
- if (inFlight.get(key) === entry)
182
- inFlight.delete(key);
194
+ if (state.inFlight.get(key) === entry)
195
+ state.inFlight.delete(key);
196
+ releaseFetcherState(fetcher, state);
183
197
  }, () => {
184
- if (inFlight.get(key) === entry)
185
- inFlight.delete(key);
198
+ if (state.inFlight.get(key) === entry)
199
+ state.inFlight.delete(key);
200
+ releaseFetcherState(fetcher, state);
186
201
  });
187
- inFlight.set(key, entry);
202
+ state.inFlight.set(key, entry);
188
203
  }
189
204
  entry.consumers++;
190
205
  let released = false;
@@ -193,13 +208,53 @@ function retainInFlight(key, fetcher, force) {
193
208
  return;
194
209
  released = true;
195
210
  entry.consumers--;
196
- if (entry.consumers === 0 && inFlight.get(key) === entry) {
211
+ if (entry.consumers === 0 && state.inFlight.get(key) === entry) {
197
212
  entry.controller.abort();
198
- inFlight.delete(key);
213
+ state.inFlight.delete(key);
214
+ releaseFetcherState(fetcher, state);
199
215
  }
200
216
  };
201
217
  return { promise: entry.promise, release };
202
218
  }
219
+ function getFetcherState(fetcher) {
220
+ let state = fetcherStates.get(fetcher);
221
+ if (!state) {
222
+ state = { cache: new Map(), inFlight: new Map() };
223
+ fetcherStates.set(fetcher, state);
224
+ }
225
+ return state;
226
+ }
227
+ function releaseFetcherState(fetcher, state) {
228
+ if (state.cache.size === 0 && state.inFlight.size === 0) {
229
+ fetcherStates.delete(fetcher);
230
+ }
231
+ }
232
+ function writeCache(fetcher, key, data, staleTime) {
233
+ const state = getFetcherState(fetcher);
234
+ const previous = state.cache.get(key);
235
+ if (previous?.expires)
236
+ clearTimeout(previous.expires);
237
+ if (staleTime <= 0) {
238
+ state.cache.delete(key);
239
+ releaseFetcherState(fetcher, state);
240
+ return;
241
+ }
242
+ const entry = { data, timestamp: Date.now(), expires: null };
243
+ if (staleTime !== Infinity) {
244
+ entry.expires = setTimeout(() => {
245
+ if (state.cache.get(key) === entry)
246
+ state.cache.delete(key);
247
+ releaseFetcherState(fetcher, state);
248
+ }, staleTime);
249
+ entry.expires.unref?.();
250
+ }
251
+ state.cache.set(key, entry);
252
+ }
253
+ function matchesPattern(key, pattern) {
254
+ return pattern.endsWith("*")
255
+ ? key.startsWith(pattern.slice(0, -1))
256
+ : key === pattern;
257
+ }
203
258
  export function mutation(fetcher, options = {}) {
204
259
  const loading = signal(false);
205
260
  const error = signal(null);
@@ -208,8 +263,14 @@ export function mutation(fetcher, options = {}) {
208
263
  // counter so `loading` stays true while ANY concurrent run is pending.
209
264
  const controllers = new Set();
210
265
  let inFlight = 0;
211
- const settle = (ac) => {
266
+ let generation = 0;
267
+ const debugTarget = {};
268
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
269
+ emitDevtools("mutation:create", debugTarget);
270
+ const settle = (ac, runGeneration) => {
212
271
  controllers.delete(ac);
272
+ if (runGeneration !== generation)
273
+ return;
213
274
  inFlight--;
214
275
  if (inFlight === 0)
215
276
  loading.set(false);
@@ -226,9 +287,12 @@ export function mutation(fetcher, options = {}) {
226
287
  c.abort();
227
288
  }
228
289
  const ac = new AbortController();
290
+ const runGeneration = generation;
229
291
  controllers.add(ac);
230
292
  inFlight++;
231
293
  loading.set(true);
294
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
295
+ emitDevtools("mutation:request", debugTarget, { args, generation });
232
296
  error.set(null);
233
297
  try {
234
298
  const result = await fetcher(args, ac.signal);
@@ -236,7 +300,9 @@ export function mutation(fetcher, options = {}) {
236
300
  throw new DOMException("aborted", "AbortError");
237
301
  }
238
302
  data.set(result);
239
- settle(ac);
303
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
304
+ emitDevtools("mutation:success", debugTarget, { args, result, generation });
305
+ settle(ac, runGeneration);
240
306
  const inv = options.invalidates;
241
307
  if (inv) {
242
308
  let patterns = [];
@@ -245,8 +311,7 @@ export function mutation(fetcher, options = {}) {
245
311
  }
246
312
  catch (err) {
247
313
  // Invalidation is best-effort. Don't fail the mutation because of it.
248
- // eslint-disable-next-line no-console
249
- console.error("[mado] mutation.invalidates threw:", err);
314
+ reportError("resource", "mutation-invalidates", "mutation invalidation threw", err);
250
315
  }
251
316
  for (const p of patterns)
252
317
  invalidate(p);
@@ -257,11 +322,16 @@ export function mutation(fetcher, options = {}) {
257
322
  if (!ac.signal.aborted) {
258
323
  error.set(err instanceof Error ? err : new Error(String(err)));
259
324
  }
260
- settle(ac);
325
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
326
+ emitDevtools("mutation:error", debugTarget, { args, error: err, generation });
327
+ settle(ac, runGeneration);
261
328
  throw err;
262
329
  }
263
330
  },
264
331
  reset() {
332
+ if (typeof __MADO_DEVTOOLS__ === "undefined" || __MADO_DEVTOOLS__)
333
+ emitDevtools("mutation:reset", debugTarget, { generation });
334
+ generation++;
265
335
  for (const c of controllers)
266
336
  c.abort();
267
337
  controllers.clear();
@@ -341,13 +411,21 @@ export const _testHooks = {
341
411
  return invalidators.size;
342
412
  },
343
413
  cacheSize() {
344
- return cache.size;
414
+ let size = 0;
415
+ for (const state of fetcherStates.values())
416
+ size += state.cache.size;
417
+ return size;
345
418
  },
346
419
  clearCache() {
347
- cache.clear();
348
- for (const entry of inFlight.values())
349
- entry.controller.abort();
350
- inFlight.clear();
420
+ for (const state of fetcherStates.values()) {
421
+ for (const entry of state.cache.values()) {
422
+ if (entry.expires)
423
+ clearTimeout(entry.expires);
424
+ }
425
+ for (const entry of state.inFlight.values())
426
+ entry.controller.abort();
427
+ }
428
+ fetcherStates.clear();
351
429
  },
352
430
  };
353
431
  //# sourceMappingURL=resource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/resource.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reactive fetch + cache. Replaces React-Query / SWR.\n *\n * Core idea:\n * 1. resource(keyFn, fetcher) — keyFn reads signals like a normal effect.\n * When dependencies change the key is recomputed, and if the key\n * actually differs — a new fetch starts (the old one is cancelled via\n * AbortController).\n * 2. Data is cached by key in a global Map.\n * 3. resource returns three signals: data/error/loading, plus\n * refresh()/mutate()/invalidate().\n *\n * mutation(fetcher) — a wrapper for POST/PUT/DELETE. After a successful run\n * it can invalidate specified resource keys (exact match or prefix-glob 'users/*').\n *\n * No runtime dependencies: only fetch + AbortController + signals.\n */\n\nimport { signal, effect, untracked, type Signal } from \"./signal.js\";\nimport { getCurrentLifecycle } from \"./lifecycle.js\";\nimport { reportError, warnOnce } from \"./diagnostics.js\";\nimport { trackStatic } from \"./static-runtime.js\";\nimport { emitDevtools } from \"./devtools-hook.js\";\n\n// ---------- Global cache ----------\n\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n expires: ReturnType<typeof setTimeout> | null;\n}\n\ntype ResourceFetcher<T> = (key: string, signal: AbortSignal) => Promise<T>;\n\ninterface InFlightEntry<T> {\n controller: AbortController;\n promise: Promise<T>;\n consumers: number;\n}\n\ninterface FetcherState {\n cache: Map<string, CacheEntry<unknown>>;\n inFlight: Map<string, InFlightEntry<unknown>>;\n}\n\nconst fetcherStates = new Map<ResourceFetcher<unknown>, FetcherState>();\nconst invalidators = new Set<(pattern: string) => void>();\n\n/**\n * Remove from cache all keys matching the pattern, and force\n * all live resource() instances with that key to re-fetch.\n *\n * Only a trailing `*` is supported for prefix-match:\n * invalidate('users/42') → exact match\n * invalidate('users/*') → everything starting with 'users/'\n * invalidate('*') → drop the ENTIRE cache (use intentionally)\n *\n * NOT supported: glob-in-middle (`users/* /posts`), regex, multi-star.\n * For more complex cases call invalidate() multiple times with different prefixes,\n * or iterate your own keys manually.\n */\nexport function invalidate(pattern: string): void {\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:invalidate\", undefined, { pattern });\n for (const [fetcher, state] of fetcherStates) {\n for (const [key, entry] of state.cache) {\n if (matchesPattern(key, pattern)) {\n if (entry.expires) clearTimeout(entry.expires);\n state.cache.delete(key);\n }\n }\n releaseFetcherState(fetcher, state);\n }\n for (const fn of invalidators) fn(pattern);\n}\n\n// ---------- resource ----------\n\n\nexport interface ResourceOptions {\n /** How many ms the data is considered fresh (fetch is skipped). */\n staleTime?: number;\n /** Initial value shown immediately. */\n initialData?: unknown;\n}\n\nexport interface Resource<T> {\n /** Signal: data or undefined */\n data: () => T | undefined;\n /** Signal: error or null */\n error: () => Error | null;\n /** Signal: whether a request is in progress */\n loading: () => boolean;\n /** Signal: current key (useful for debugging and DI) */\n key: () => string;\n /** Force re-run the request. */\n refresh(): Promise<T>;\n /**\n * Locally replace the data (optimistic update).\n * The cache is also updated.\n */\n mutate(next: T | ((prev: T | undefined) => T)): void;\n}\n\nexport function resource<T>(\n keyFn: () => string,\n fetcher: ResourceFetcher<T>,\n options: ResourceOptions = {},\n): Resource<T> {\n const data = signal<T | undefined>(options.initialData as T | undefined);\n const error = signal<Error | null>(null);\n const loading = signal(false);\n const keySig = signal<string>(\"\");\n const debugTarget = {};\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:create\", debugTarget);\n\n let releaseInFlight: (() => void) | null = null;\n let requestSeq = 0;\n let lastKey = \"\";\n let force = false;\n\n // if inside component-setup — auto-cleanup on unmount.\n // if outside — print a warning so the developer knows\n // about the potential leak.\n const lifecycle = getCurrentLifecycle();\n if (!lifecycle) {\n warnOnce(\n \"resource-outside-lifecycle\",\n \"resource() called outside of component-setup. \" +\n \"Invalidator subscriptions will not be cleaned up automatically — \" +\n \"this is a leak. Use resource() inside component(...), or \" +\n \"manage the lifecycle manually via createLifecycle()/runInLifecycle().\",\n );\n }\n\n const run = (key: string): Promise<T> => {\n releaseInFlight?.();\n releaseInFlight = null;\n const seq = ++requestSeq;\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:request\", debugTarget, { key, seq, force });\n\n // if there is a fresh cache and not forced — use it\n const cached = getFetcherState(fetcher).cache.get(key) as CacheEntry<T> | undefined;\n if (\n cached &&\n !force &&\n (options.staleTime === Infinity ||\n Date.now() - cached.timestamp < (options.staleTime ?? 0))\n ) {\n data.set(cached.data);\n error.set(null);\n loading.set(false);\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:cache-hit\", debugTarget, { key });\n return Promise.resolve(cached.data);\n }\n\n loading.set(true);\n error.set(null);\n\n const retained = retainInFlight(key, fetcher, force);\n releaseInFlight = retained.release;\n force = false;\n\n retained.promise.then(\n (result) => {\n // Two-layer staleness check:\n // 1. seq !== requestSeq — this resource has moved to a newer run().\n // 2. key !== lastKey — defensive guard for fetchers that ignore\n // the AbortSignal and resolve after a newer run() has started.\n // Without this, a slow stale response can overwrite the data\n // from a faster newer one when the key changes rapidly.\n retained.release();\n if (seq !== requestSeq) return;\n if (key !== lastKey) return;\n writeCache(fetcher, key, result, options.staleTime ?? 0);\n data.set(result);\n loading.set(false);\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:success\", debugTarget, { key, seq, result });\n },\n (err: unknown) => {\n retained.release();\n if (seq !== requestSeq) return;\n if (key !== lastKey) return;\n error.set(err instanceof Error ? err : new Error(String(err)));\n loading.set(false);\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:error\", debugTarget, { key, seq, error: err });\n },\n );\n return retained.promise;\n };\n\n // subscribe to key changes\n const stopKeyEffect = effect(() => {\n const key = keyFn();\n keySig.set(key);\n if (key !== lastKey || force) {\n lastKey = key;\n void run(key);\n }\n });\n\n // subscribe to global invalidation\n const onInv = (pattern: string) => {\n if (matchesPattern(lastKey, pattern)) {\n force = true;\n void run(lastKey);\n }\n };\n invalidators.add(onInv);\n\n // auto-cleanup if inside a component\n if (lifecycle) {\n lifecycle.onDispose(() => {\n requestSeq++;\n stopKeyEffect();\n invalidators.delete(onInv);\n releaseInFlight?.();\n releaseInFlight = null;\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"resource:dispose\", debugTarget, { key: lastKey });\n });\n }\n\n return {\n data,\n error,\n loading,\n key: keySig,\n refresh() {\n force = true;\n // read key without tracking — otherwise we'd end up inside someone else's effect\n const key = untracked(keyFn);\n lastKey = key;\n keySig.set(key);\n return run(key);\n },\n mutate(next) {\n const prev = data.peek();\n const value =\n typeof next === \"function\"\n ? (next as (p: T | undefined) => T)(prev)\n : next;\n data.set(value);\n if (lastKey) writeCache(fetcher, lastKey, value, options.staleTime ?? 0);\n },\n };\n}\n\nfunction retainInFlight<T>(\n key: string,\n fetcher: ResourceFetcher<T>,\n force: boolean,\n): { promise: Promise<T>; release: () => void } {\n const state = getFetcherState(fetcher);\n let entry = (!force ? state.inFlight.get(key) : undefined) as\n | InFlightEntry<T>\n | undefined;\n\n if (!entry) {\n const controller = new AbortController();\n entry = {\n controller,\n consumers: 0,\n promise: trackStatic(fetcher(key, controller.signal), `resource ${key}`),\n };\n entry.promise.then(\n () => {\n if (state.inFlight.get(key) === entry) state.inFlight.delete(key);\n releaseFetcherState(fetcher, state);\n },\n () => {\n if (state.inFlight.get(key) === entry) state.inFlight.delete(key);\n releaseFetcherState(fetcher, state);\n },\n );\n state.inFlight.set(key, entry as InFlightEntry<unknown>);\n }\n\n entry.consumers++;\n let released = false;\n const release = () => {\n if (released) return;\n released = true;\n entry.consumers--;\n if (entry.consumers === 0 && state.inFlight.get(key) === entry) {\n entry.controller.abort();\n state.inFlight.delete(key);\n releaseFetcherState(fetcher, state);\n }\n };\n\n return { promise: entry.promise, release };\n}\n\nfunction getFetcherState<T>(fetcher: ResourceFetcher<T>): FetcherState {\n let state = fetcherStates.get(fetcher as ResourceFetcher<unknown>);\n if (!state) {\n state = { cache: new Map(), inFlight: new Map() };\n fetcherStates.set(fetcher as ResourceFetcher<unknown>, state);\n }\n return state;\n}\n\nfunction releaseFetcherState(\n fetcher: ResourceFetcher<unknown>,\n state: FetcherState,\n): void {\n if (state.cache.size === 0 && state.inFlight.size === 0) {\n fetcherStates.delete(fetcher);\n }\n}\n\nfunction writeCache<T>(\n fetcher: ResourceFetcher<T>,\n key: string,\n data: T,\n staleTime: number,\n): void {\n const state = getFetcherState(fetcher);\n const previous = state.cache.get(key);\n if (previous?.expires) clearTimeout(previous.expires);\n if (staleTime <= 0) {\n state.cache.delete(key);\n releaseFetcherState(fetcher as ResourceFetcher<unknown>, state);\n return;\n }\n const entry: CacheEntry<T> = { data, timestamp: Date.now(), expires: null };\n if (staleTime !== Infinity) {\n entry.expires = setTimeout(() => {\n if (state.cache.get(key) === entry) state.cache.delete(key);\n releaseFetcherState(fetcher as ResourceFetcher<unknown>, state);\n }, staleTime);\n (entry.expires as ReturnType<typeof setTimeout> & { unref?: () => void }).unref?.();\n }\n state.cache.set(key, entry as CacheEntry<unknown>);\n}\n\nfunction matchesPattern(key: string, pattern: string): boolean {\n return pattern.endsWith(\"*\")\n ? key.startsWith(pattern.slice(0, -1))\n : key === pattern;\n}\n\n// ---------- mutation ----------\n\n\nexport interface MutationOptions<TArgs = unknown, TResult = unknown> {\n /**\n * Invalidate cache by these patterns after success.\n *\n * Can be:\n * - a static array: `['users/*']`\n * - a function of result and args:\n * `(result, args) => [${'`'}posts/${result.id}${'`'}, 'feed/*']`\n *\n * The function is called AFTER a successful request. If it throws — the error\n * is logged to console, but the mutation success is preserved (invalidation is best-effort).\n *\n * Only `*` at the END of a pattern is supported (see invalidate()).\n */\n invalidates?:\n | readonly string[]\n | ((result: TResult, args: TArgs) => readonly string[]);\n /**\n * Abort the previous in-flight run when a new run starts.\n *\n * Default: `false`. Mutations (POST/PUT/DELETE) are concurrent by default —\n * two quick submits of different entities must both complete; client-side\n * aborting the first would drop its `invalidates` even though the server\n * likely applied it. Set `true` only for last-write-wins flows like\n * search-as-you-type, where stale in-flight requests should be cancelled.\n */\n abortPrevious?: boolean;\n}\n\n\nexport interface Mutation<TArgs, TResult> {\n /** Signal: request in progress */\n loading: Signal<boolean>;\n /** Signal: error */\n error: Signal<Error | null>;\n /** Signal: last received data */\n data: Signal<TResult | undefined>;\n /** Execute. Returns a Promise. */\n run(args: TArgs): Promise<TResult>;\n /** Reset error/data state. */\n reset(): void;\n}\n\nexport function mutation<TArgs, TResult>(\n fetcher: (args: TArgs, signal: AbortSignal) => Promise<TResult>,\n options: MutationOptions<TArgs, TResult> = {},\n): Mutation<TArgs, TResult> {\n const loading = signal(false);\n const error = signal<Error | null>(null);\n const data = signal<TResult | undefined>(undefined);\n // Track every controller so reset() can abort them all; `inFlight` is a\n // counter so `loading` stays true while ANY concurrent run is pending.\n const controllers = new Set<AbortController>();\n let inFlight = 0;\n let generation = 0;\n const debugTarget = {};\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"mutation:create\", debugTarget);\n\n const settle = (ac: AbortController, runGeneration: number): void => {\n controllers.delete(ac);\n if (runGeneration !== generation) return;\n inFlight--;\n if (inFlight === 0) loading.set(false);\n };\n\n return {\n loading,\n error,\n data,\n async run(args) {\n // Mutations are concurrent by default — only abort the previous run when\n // explicitly opted in (search-as-you-type). (FABLE_REPORT.md finding #6)\n if (options.abortPrevious) {\n for (const c of controllers) c.abort();\n }\n const ac = new AbortController();\n const runGeneration = generation;\n controllers.add(ac);\n inFlight++;\n loading.set(true);\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"mutation:request\", debugTarget, { args, generation });\n error.set(null);\n try {\n const result = await fetcher(args, ac.signal);\n if (ac.signal.aborted) {\n throw new DOMException(\"aborted\", \"AbortError\");\n }\n data.set(result);\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"mutation:success\", debugTarget, { args, result, generation });\n settle(ac, runGeneration);\n const inv = options.invalidates;\n if (inv) {\n let patterns: readonly string[] = [];\n try {\n patterns = typeof inv === \"function\" ? inv(result, args) : inv;\n } catch (err) {\n // Invalidation is best-effort. Don't fail the mutation because of it.\n reportError(\"resource\", \"mutation-invalidates\", \"mutation invalidation threw\", err);\n }\n for (const p of patterns) invalidate(p);\n }\n return result;\n } catch (err) {\n if (!ac.signal.aborted) {\n error.set(err instanceof Error ? err : new Error(String(err)));\n }\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"mutation:error\", debugTarget, { args, error: err, generation });\n settle(ac, runGeneration);\n throw err;\n }\n },\n reset() {\n if (typeof __MADO_DEVTOOLS__ === \"undefined\" || __MADO_DEVTOOLS__) emitDevtools(\"mutation:reset\", debugTarget, { generation });\n generation++;\n for (const c of controllers) c.abort();\n controllers.clear();\n inFlight = 0;\n loading.set(false);\n error.set(null);\n data.set(undefined);\n },\n };\n}\n\n\n// ---------- Utilities ----------\n\n\n/**\n * Extended HTTP error thrown by jsonFetcher() on `!response.ok`.\n *\n * Unlike a plain `Error(\"HTTP 422\")`, it preserves:\n * - `status` / `statusText` — for UI discrimination (\"422 → show form errors\")\n * - `url` — which endpoint failed\n * - `body` — parsed response body (JSON if possible, then text, then null)\n *\n * try {\n * await api.save(user);\n * } catch (err) {\n * if (err instanceof HttpError && err.status === 422) {\n * // err.body may contain { errors: { email: 'taken' } }\n * }\n * }\n */\nexport class HttpError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly url: string;\n readonly body: unknown;\n\n constructor(\n status: number,\n statusText: string,\n url: string,\n body: unknown,\n ) {\n super(`HTTP ${status} ${statusText} ${url}`);\n this.name = \"HttpError\";\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n\n/**\n * Simple JSON fetcher for resource. Throws HttpError on `!response.ok`,\n * with a parsed body (JSON → text → null) for proper UI error handling.\n *\n * const user = resource(() => `/api/users/${id()}`, jsonFetcher());\n */\nexport function jsonFetcher<T>(\n init: RequestInit = {},\n): (url: string, signal: AbortSignal) => Promise<T> {\n return async (url, signal) => {\n const res = await fetch(url, { ...init, signal });\n if (!res.ok) {\n let body: unknown = null;\n // Try to read the body: JSON first, then text. Don't fail if that doesn't work.\n try {\n const ct = res.headers.get(\"content-type\") ?? \"\";\n if (ct.includes(\"application/json\")) {\n body = await res.json();\n } else {\n body = await res.text();\n }\n } catch {\n body = null;\n }\n throw new HttpError(res.status, res.statusText, url, body);\n }\n return (await res.json()) as T;\n };\n}\n\n// ---------- Test hooks ----------\n//\n// Not public API. Used by tests to inspect lifecycle cleanup.\n\n/** @internal */\nexport const _testHooks = {\n invalidatorsSize(): number {\n return invalidators.size;\n },\n cacheSize(): number {\n let size = 0;\n for (const state of fetcherStates.values()) size += state.cache.size;\n return size;\n },\n clearCache(): void {\n for (const state of fetcherStates.values()) {\n for (const entry of state.cache.values()) {\n if (entry.expires) clearTimeout(entry.expires);\n }\n for (const entry of state.inFlight.values()) entry.controller.abort();\n }\n fetcherStates.clear();\n },\n};\n"]}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Normalise an arbitrary base value into the canonical Mado form:
3
+ * starts with "/", ends with "/", collapses repeated slashes. The root
4
+ * base is the literal "/".
5
+ *
6
+ * normalizeBase("") === "/"
7
+ * normalizeBase("/") === "/"
8
+ * normalizeBase("mado") === "/mado/"
9
+ * normalizeBase("/mado") === "/mado/"
10
+ * normalizeBase("/mado/") === "/mado/"
11
+ * normalizeBase("//x//y/") === "/x/y/"
12
+ */
13
+ export declare function normalizeBase(raw: string | null | undefined): string;
14
+ /**
15
+ * The active base prefix for the running app. Computed once from
16
+ * `import.meta.env.BASE_URL` and normalised. Use it inside Mado runtime;
17
+ * application code should call `routeUrl()` instead.
18
+ */
19
+ export declare const appBase: string;
20
+ /**
21
+ * Strip the base prefix off a browser pathname so it becomes a route
22
+ * pathname the matcher understands.
23
+ *
24
+ * base = "/mado/"
25
+ * stripBase("/mado/") === "/"
26
+ * stripBase("/mado/docs") === "/docs"
27
+ * stripBase("/mado/docs/") === "/docs"
28
+ * stripBase("/other") === "/other" (no base → unchanged)
29
+ * stripBase("") === "/"
30
+ *
31
+ * base = "/"
32
+ * stripBase("/docs") === "/docs"
33
+ */
34
+ export declare function stripBase(pathname: string, base?: string): string;
35
+ /**
36
+ * Prefix a route pathname with the active base so it becomes a real
37
+ * browser URL suitable for `history.pushState` and `<a href>`.
38
+ *
39
+ * base = "/mado/"
40
+ * withBase("/") === "/mado/"
41
+ * withBase("/docs") === "/mado/docs"
42
+ * withBase("/docs/", b) === "/mado/docs/"
43
+ * withBase("docs") === "/mado/docs"
44
+ *
45
+ * base = "/"
46
+ * withBase("/docs") === "/docs"
47
+ */
48
+ export declare function withBase(pathname: string, base?: string): string;
49
+ /**
50
+ * Build an internal link URL: prefix the given route pathname with the
51
+ * active Vite base, preserving query and hash. This is the canonical way
52
+ * to emit `<a href>` values in Mado views.
53
+ *
54
+ * import { routeUrl } from "@madojs/mado";
55
+ * html`<a data-link href=${routeUrl("/docs")}>Docs</a>`
56
+ *
57
+ * base = "/mado/"
58
+ * routeUrl("/docs") === "/mado/docs"
59
+ * routeUrl("/docs?q=1#h") === "/mado/docs?q=1#h"
60
+ * routeUrl("/") === "/mado/"
61
+ *
62
+ * base = "/"
63
+ * routeUrl("/docs") === "/docs"
64
+ */
65
+ export declare function routeUrl(pathname: string, base?: string): string;
66
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/router/base.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAQpE;AAED;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,MAAqC,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAgB,GAAG,MAAM,CAgB1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAgB,GAAG,MAAM,CAezE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAgB,GAAG,MAAM,CAiBzE"}