@madojs/mado 0.11.0 → 0.12.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 (221) hide show
  1. package/AGENTS.md +102 -25
  2. package/CHANGELOG.md +185 -1
  3. package/README.md +137 -172
  4. package/dist/src/component.d.ts +3 -2
  5. package/dist/src/component.js +98 -6
  6. package/dist/src/component.js.map +1 -1
  7. package/dist/src/css.js +34 -5
  8. package/dist/src/css.js.map +1 -1
  9. package/dist/src/head.d.ts +6 -6
  10. package/dist/src/head.js +6 -6
  11. package/dist/src/html/bindings.js +3 -3
  12. package/dist/src/html/bindings.js.map +1 -1
  13. package/dist/src/html/parser.d.ts +1 -1
  14. package/dist/src/html/parser.js +1 -1
  15. package/dist/src/html/template.js +24 -10
  16. package/dist/src/html/template.js.map +1 -1
  17. package/dist/src/index.d.ts +8 -4
  18. package/dist/src/index.js +13 -3
  19. package/dist/src/index.js.map +1 -1
  20. package/dist/src/page.d.ts +62 -28
  21. package/dist/src/page.js +5 -0
  22. package/dist/src/page.js.map +1 -1
  23. package/dist/src/resource.js +2 -1
  24. package/dist/src/resource.js.map +1 -1
  25. package/dist/src/router/base.d.ts +65 -0
  26. package/dist/src/router/base.js +168 -0
  27. package/dist/src/router/base.js.map +1 -0
  28. package/dist/src/router/manifest.js +75 -31
  29. package/dist/src/router/manifest.js.map +1 -1
  30. package/dist/src/router/match.d.ts +16 -2
  31. package/dist/src/router/match.js +41 -1
  32. package/dist/src/router/match.js.map +1 -1
  33. package/dist/src/router/navigation.js +58 -9
  34. package/dist/src/router/navigation.js.map +1 -1
  35. package/dist/src/static-runtime.d.ts +81 -0
  36. package/dist/src/static-runtime.js +209 -0
  37. package/dist/src/static-runtime.js.map +1 -0
  38. package/dist/src/vite/index.d.ts +31 -3
  39. package/dist/src/vite/index.js +49 -18
  40. package/dist/src/vite/index.js.map +1 -1
  41. package/docs/README.md +5 -8
  42. package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
  43. package/docs/en/00-the-mado-way.md +1 -1
  44. package/docs/en/01-quickstart.md +183 -0
  45. package/docs/en/10-pages-and-components.md +271 -0
  46. package/docs/en/11-templates-and-signals.md +211 -0
  47. package/docs/en/12-routing.md +229 -0
  48. package/docs/en/13-data.md +225 -0
  49. package/docs/en/14-forms.md +244 -0
  50. package/docs/en/15-static-snapshots.md +181 -0
  51. package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +53 -2
  52. package/docs/en/{13-deployment.md → 20-deployment.md} +59 -10
  53. package/docs/en/{14-testing.md → 22-testing.md} +6 -5
  54. package/docs/en/23-cookbook.md +292 -0
  55. package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +12 -3
  56. package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +3 -3
  57. package/docs/en/40-llm-guide.md +776 -0
  58. package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +15 -16
  59. package/docs/en/{05-why-mado.md → 42-why-mado.md} +1 -1
  60. package/docs/en/README.md +97 -27
  61. package/docs/recipes/nginx/Containerfile +26 -0
  62. package/docs/recipes/nginx/nginx.conf +42 -0
  63. package/llms.txt +246 -211
  64. package/package.json +17 -10
  65. package/scripts/bake.mjs +4 -568
  66. package/scripts/cli/generate.mjs +55 -5
  67. package/scripts/cli/help.mjs +11 -5
  68. package/scripts/cli/index.mjs +20 -4
  69. package/scripts/cli/init.mjs +7 -2
  70. package/scripts/cli/release.mjs +20 -68
  71. package/scripts/docs-lint.mjs +170 -0
  72. package/scripts/package-smoke.mjs +67 -9
  73. package/scripts/preview.mjs +95 -6
  74. package/scripts/size-budget.mjs +5 -1
  75. package/scripts/static/browser.mjs +654 -0
  76. package/scripts/static/discover.mjs +281 -0
  77. package/scripts/static/output.mjs +141 -0
  78. package/scripts/static/serialize.mjs +212 -0
  79. package/scripts/static/server.mjs +167 -0
  80. package/scripts/static.mjs +191 -0
  81. package/starters/default/README.md +57 -55
  82. package/starters/default/package.json +3 -9
  83. package/starters/default/src/app.routes.ts +20 -33
  84. package/starters/default/src/components/feature-card.component.ts +40 -0
  85. package/starters/default/src/components/live-counter.component.ts +57 -0
  86. package/starters/default/src/content/guides.ts +55 -0
  87. package/starters/default/src/main.ts +9 -13
  88. package/starters/default/src/pages/app.page.ts +41 -0
  89. package/starters/default/src/pages/guide.page.ts +40 -0
  90. package/starters/default/src/pages/home.page.ts +49 -0
  91. package/starters/default/src/pages/not-found.page.ts +18 -0
  92. package/starters/default/src/styles/document.css +39 -0
  93. package/starters/default/src/styles/reset.css +37 -0
  94. package/starters/default/src/styles/tokens.css +30 -0
  95. package/starters/default/src/styles.d.ts +3 -1
  96. package/starters/default/src/vite-env.d.ts +1 -1
  97. package/starters/default/vite.config.ts +14 -1
  98. package/starters/modular/README.md +142 -0
  99. package/starters/modular/index.html +13 -0
  100. package/starters/modular/package.json +30 -0
  101. package/starters/modular/src/app.routes.ts +39 -0
  102. package/starters/{default → modular}/src/layouts/app-shell.layout.ts +8 -5
  103. package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
  104. package/starters/modular/src/main.ts +16 -0
  105. package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +3 -3
  106. package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
  107. package/starters/modular/src/modules/home/not-found.page.ts +14 -0
  108. package/starters/modular/src/styles.d.ts +1 -0
  109. package/starters/modular/src/vite-env.d.ts +1 -0
  110. package/starters/modular/tsconfig.json +24 -0
  111. package/starters/modular/vite.config.ts +131 -0
  112. package/TODO.md +0 -79
  113. package/docs/en/01-routing.md +0 -152
  114. package/docs/en/02-project-layout.md +0 -124
  115. package/docs/en/03-static-bake.md +0 -249
  116. package/docs/en/04-ide-setup.md +0 -162
  117. package/docs/en/07-llm-pitfalls.md +0 -724
  118. package/docs/en/08-llm-zero-history-test.md +0 -56
  119. package/docs/en/09-shadow-vs-light-dom.md +0 -174
  120. package/docs/en/11-layouts.md +0 -113
  121. package/docs/en/12-auth-and-api.md +0 -124
  122. package/docs/en/16-bake-cookbook.md +0 -100
  123. package/docs/en/17-shadow-dom-forms.md +0 -192
  124. package/docs/fr/00-the-mado-way.md +0 -85
  125. package/docs/fr/01-routing.md +0 -120
  126. package/docs/fr/02-project-layout.md +0 -84
  127. package/docs/fr/03-static-bake.md +0 -289
  128. package/docs/fr/04-ide-setup.md +0 -162
  129. package/docs/fr/05-why-mado.md +0 -193
  130. package/docs/fr/06-for-backenders.md +0 -438
  131. package/docs/fr/07-llm-pitfalls.md +0 -625
  132. package/docs/fr/08-llm-zero-history-test.md +0 -38
  133. package/docs/fr/09-shadow-vs-light-dom.md +0 -65
  134. package/docs/fr/10-app-architecture.md +0 -138
  135. package/docs/fr/11-layouts.md +0 -47
  136. package/docs/fr/12-auth-and-api.md +0 -76
  137. package/docs/fr/13-deployment.md +0 -57
  138. package/docs/fr/14-testing.md +0 -41
  139. package/docs/fr/15-error-handling.md +0 -50
  140. package/docs/fr/16-bake-cookbook.md +0 -88
  141. package/docs/fr/17-shadow-dom-forms.md +0 -196
  142. package/docs/fr/18-api-freeze-map.md +0 -63
  143. package/docs/fr/19-reactivity-ordering.md +0 -97
  144. package/docs/fr/20-v1-stability.md +0 -88
  145. package/docs/fr/README.md +0 -27
  146. package/docs/ru/00-the-mado-way.md +0 -84
  147. package/docs/ru/01-routing.md +0 -119
  148. package/docs/ru/02-project-layout.md +0 -84
  149. package/docs/ru/03-static-bake.md +0 -250
  150. package/docs/ru/04-ide-setup.md +0 -144
  151. package/docs/ru/05-why-mado.md +0 -193
  152. package/docs/ru/06-for-backenders.md +0 -428
  153. package/docs/ru/07-llm-pitfalls.md +0 -624
  154. package/docs/ru/08-llm-zero-history-test.md +0 -57
  155. package/docs/ru/09-shadow-vs-light-dom.md +0 -63
  156. package/docs/ru/10-app-architecture.md +0 -152
  157. package/docs/ru/11-layouts.md +0 -47
  158. package/docs/ru/12-auth-and-api.md +0 -75
  159. package/docs/ru/13-deployment.md +0 -66
  160. package/docs/ru/14-testing.md +0 -50
  161. package/docs/ru/15-error-handling.md +0 -56
  162. package/docs/ru/16-bake-cookbook.md +0 -95
  163. package/docs/ru/17-shadow-dom-forms.md +0 -193
  164. package/docs/ru/18-api-freeze-map.md +0 -64
  165. package/docs/ru/19-reactivity-ordering.md +0 -95
  166. package/docs/ru/20-v1-stability.md +0 -82
  167. package/docs/ru/README.md +0 -25
  168. package/docs/uk/00-the-mado-way.md +0 -82
  169. package/docs/uk/01-routing.md +0 -76
  170. package/docs/uk/02-project-layout.md +0 -73
  171. package/docs/uk/03-static-bake.md +0 -48
  172. package/docs/uk/04-ide-setup.md +0 -26
  173. package/docs/uk/05-why-mado.md +0 -34
  174. package/docs/uk/06-for-backenders.md +0 -55
  175. package/docs/uk/07-llm-pitfalls.md +0 -145
  176. package/docs/uk/08-llm-zero-history-test.md +0 -34
  177. package/docs/uk/09-shadow-vs-light-dom.md +0 -58
  178. package/docs/uk/10-app-architecture.md +0 -97
  179. package/docs/uk/11-layouts.md +0 -47
  180. package/docs/uk/12-auth-and-api.md +0 -70
  181. package/docs/uk/13-deployment.md +0 -40
  182. package/docs/uk/14-testing.md +0 -34
  183. package/docs/uk/15-error-handling.md +0 -32
  184. package/docs/uk/16-bake-cookbook.md +0 -36
  185. package/docs/uk/17-shadow-dom-forms.md +0 -193
  186. package/docs/uk/18-api-freeze-map.md +0 -61
  187. package/docs/uk/19-reactivity-ordering.md +0 -95
  188. package/docs/uk/20-v1-stability.md +0 -83
  189. package/docs/uk/README.md +0 -27
  190. package/starters/default/src/modules/home/not-found.page.ts +0 -11
  191. /package/docs/en/{15-error-handling.md → 21-error-handling.md} +0 -0
  192. /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
  193. /package/starters/{default → modular}/.editorconfig +0 -0
  194. /package/starters/{default → modular}/eslint.config.mjs +0 -0
  195. /package/starters/{default → modular}/public/favicon.svg +0 -0
  196. /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
  197. /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
  198. /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
  199. /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
  200. /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
  201. /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
  202. /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
  203. /package/starters/{default → modular}/src/modules/auth/login.page.ts +0 -0
  204. /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
  205. /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
  206. /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
  207. /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
  208. /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
  209. /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
  210. /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
  211. /package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +0 -0
  212. /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
  213. /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
  214. /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
  215. /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
  216. /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
  217. /package/starters/{default → modular}/src/shared/styles/reset.css +0 -0
  218. /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
  219. /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
  220. /package/starters/{default → modular}/src/shared/ui/x-button.component.ts +0 -0
  221. /package/starters/{default → modular}/src/shared/ui/x-spinner.component.ts +0 -0
@@ -1,65 +0,0 @@
1
- # Shadow DOM vs Light DOM
2
-
3
- Les composants Mado utilisent Shadow DOM par défaut. C'est un bon défaut pour
4
- les widgets autonomes, mais les zones d'application et les pages restent
5
- généralement de simples templates light DOM.
6
-
7
- ## Règle
8
-
9
- Utilisez les route layouts pour les zones d'application :
10
-
11
- ```ts
12
- export default page({
13
- view: ({ child }) => html`<main class="app-main">${child}</main>`,
14
- });
15
- ```
16
-
17
- Ces fichiers vivent dans `src/layouts/` et sont composés depuis
18
- `src/app.routes.ts` avec `layout()`. Ils sont stylés par
19
- `src/shared/styles/shell.css`.
20
-
21
- Utilisez les page files pour les écrans :
22
-
23
- ```ts
24
- export default page({
25
- view: () => html`<section><h1>Users</h1></section>`,
26
- });
27
- ```
28
-
29
- Les tables, forms, prose et états simples de page sont stylés par
30
- `src/shared/styles/content.css`.
31
-
32
- Utilisez Shadow DOM components pour les widgets feuilles :
33
-
34
- - buttons, badges, cards, metrics ;
35
- - spinners, modals, toasts ;
36
- - widgets qui doivent posséder leur CSS.
37
-
38
- ```ts
39
- component("x-status-badge", ({ attr }) => {
40
- const status = attr("status", "draft");
41
- return () => html`<span>${status}</span>`;
42
- }, {
43
- styles: css`
44
- :host { display: inline-block; }
45
- span { color: var(--color-text-muted); }
46
- `,
47
- });
48
- ```
49
-
50
- ## Comment les styles se comportent
51
-
52
- - `tokens.css` définit des CSS custom properties ; `var(...)` traverse Shadow
53
- DOM.
54
- - `reset.css`, `shell.css`, `content.css` s'appliquent seulement au document /
55
- light DOM.
56
- - Les sélecteurs de classe comme `.data`, `.app-main`, `.error` ne traversent
57
- pas Shadow DOM.
58
- - Les styles locaux des composants vivent dans ``css`...` `` dans les options de
59
- `component()`.
60
- - Si un Shadow component accepte des enfants, utilisez `<slot>` et stylisez le
61
- frame dans les styles du composant.
62
-
63
- Si une page semble sans style, vous avez probablement utilisé des classes
64
- globales dans un Shadow DOM component. Déplacez le markup dans une page/layout
65
- ou déplacez le CSS dans les styles du composant.
@@ -1,138 +0,0 @@
1
- # Architecture d'application
2
-
3
- Le starter officiel est la forme canonique d'une application Mado en
4
- production. Ce n'est pas un framework dans le framework : seulement des
5
- fichiers, des imports, les primitives Mado et des limites ESLint.
6
-
7
- ## Structure
8
-
9
- ```txt
10
- src/
11
- ├── main.ts
12
- ├── app.routes.ts
13
- ├── layouts/
14
- │ ├── app-shell.layout.ts
15
- │ └── auth-shell.layout.ts
16
- ├── shared/
17
- │ ├── http/
18
- │ ├── lib/
19
- │ ├── styles/
20
- │ └── ui/
21
- └── modules/
22
- ├── auth/
23
- │ ├── auth.routes.ts
24
- │ ├── auth.public.ts
25
- │ ├── auth.service.ts
26
- │ ├── auth.connector.ts
27
- │ ├── auth.guard.ts
28
- │ ├── login.page.ts
29
- │ └── _contracts/
30
- └── billing/
31
- ├── billing.routes.ts
32
- ├── billing.public.ts
33
- ├── billing.types.ts
34
- ├── api/
35
- ├── data/
36
- ├── pages/
37
- ├── components/
38
- └── _contracts/
39
- ```
40
-
41
- ## App Map
42
-
43
- `src/app.routes.ts` est la carte de toute l'application. Les modules exportent
44
- des route maps simples ; les app routes décident quel shell et quel guard
45
- enveloppent chaque zone.
46
-
47
- ```ts
48
- import { layout, routes } from "@madojs/mado";
49
- import { requireAuth } from "./modules/auth/auth.public";
50
- import { authRoutes } from "./modules/auth/auth.routes";
51
- import { billingRoutes } from "./modules/billing/billing.routes";
52
-
53
- export const manifest = {
54
- "/": () => import("./modules/home/home.page"),
55
- "/login": layout({
56
- layout: () => import("./layouts/auth-shell.layout"),
57
- routes: authRoutes,
58
- }),
59
- "/billing": layout({
60
- layout: () => import("./layouts/app-shell.layout"),
61
- guard: requireAuth,
62
- routes: billingRoutes,
63
- }),
64
- "*": () => import("./modules/home/not-found.page"),
65
- };
66
-
67
- export default routes(manifest);
68
- ```
69
-
70
- Rules:
71
-
72
- - Export `manifest` pour `mado bake`.
73
- - Les modules n'appellent jamais `layout()`.
74
- - Les layouts décrivent des zones d'application, pas des domaines.
75
- - Ne cachez pas le router dans un custom element ou un second shell dans
76
- `main.ts`.
77
-
78
- ## File Forms
79
-
80
- | Suffix | Role |
81
- | --- | --- |
82
- | `*.page.ts` | route page, default `page({...})` |
83
- | `*.layout.ts` | app-zone wrapper, default `page(...)` |
84
- | `*.connector.ts` | one external API system |
85
- | `*.resource.ts` | `resource()` and `mutation()` layer |
86
- | `*.service.ts` | module singleton state |
87
- | `*.guard.ts` | route guard |
88
- | `*.routes.ts` | module-local route map |
89
- | `*.public.ts` | only public module surface |
90
- | `*.types.ts` | domain types |
91
- | `*.component.ts` | Web Component registration |
92
-
93
- Les signals, resources et forms locaux à une page vivent dans `view()`. L'état
94
- partagé par un module vit dans `*.service.ts`.
95
-
96
- ## Data Flow
97
-
98
- ```txt
99
- shared/http/http-client.ts
100
-
101
- modules/<x>/api/*.connector.ts DTO -> domain mapping
102
-
103
- modules/<x>/data/*.resource.ts cache keys + mutations
104
-
105
- modules/<x>/pages/*.page.ts UI consumes domain types
106
- ```
107
-
108
- ## Styles
109
-
110
- | File | Role |
111
- | --- | --- |
112
- | `src/shared/styles/tokens.css` | design tokens as CSS custom properties |
113
- | `src/shared/styles/reset.css` | document/light DOM reset |
114
- | `src/shared/styles/shell.css` | app-zone layouts from `src/layouts/` |
115
- | `src/shared/styles/content.css` | page-level forms, tables, prose and states |
116
-
117
- Les composants feuilles gardent leurs styles dans ``css`...` `` dans les
118
- options de `component()` et dépendent des tokens, pas de classes globales.
119
-
120
- `vite.config.ts` active le transformer Lightning CSS de Vite. Mado ne possède
121
- pas le prefixing, le lowering CSS ou la minification.
122
-
123
- ## CLI
124
-
125
- ```bash
126
- mado new module billing
127
- mado new page billing/pages/invoices-list
128
- mado new connector billing/api/stripe
129
- mado new resource billing/data/invoices
130
- mado new service billing/cart
131
- mado new form billing/invoice
132
- mado new component billing/components/invoice-status-badge
133
- mado new guard billing/billing
134
- mado new layout app-shell
135
- ```
136
-
137
- Le générateur écrit seulement de nouveaux fichiers. Il ne modifie pas
138
- `app.routes.ts`.
@@ -1,47 +0,0 @@
1
- # Layouts
2
-
3
- Le chemin recommandé pour les layouts Mado est un route group dans
4
- `src/app.routes.ts`. Ne mettez pas un shell global dans `main.ts` si l'app a
5
- plusieurs zones : public, auth, app, embed.
6
-
7
- ```ts
8
- import { layout, routes } from "@madojs/mado";
9
- import { requireAuth } from "./modules/auth/auth.public";
10
- import { authRoutes } from "./modules/auth/auth.routes";
11
- import { billingRoutes } from "./modules/billing/billing.routes";
12
-
13
- export const manifest = {
14
- "/": () => import("./modules/home/home.page.js"),
15
- "/login": layout({
16
- layout: () => import("./layouts/auth-shell.layout.js"),
17
- routes: authRoutes,
18
- }),
19
- "/billing": layout({
20
- layout: () => import("./layouts/app-shell.layout.js"),
21
- guard: requireAuth,
22
- routes: billingRoutes,
23
- }),
24
- "*": () => import("./modules/home/not-found.page.js"),
25
- };
26
-
27
- export default routes(manifest);
28
- ```
29
-
30
- Un layout est une `page({ view })` qui rend `child` :
31
-
32
- ```ts
33
- export default page({
34
- view: ({ child }) => html`
35
- <div class="layout layout--app">
36
- <main class="app-main">${child}</main>
37
- </div>
38
- `,
39
- });
40
- ```
41
-
42
- Rules:
43
-
44
- - one shell per route group, not per page;
45
- - modules export plain route maps and do not call `layout()`;
46
- - a guard on the group protects the whole subtree;
47
- - layout view stays stateless; page-local state lives in pages/components/resources.
@@ -1,76 +0,0 @@
1
- # Auth et API
2
-
3
- Le starter par défaut est la recette recommandée. La mécanique HTTP vit dans
4
- `src/shared/http/`, l'état auth dans `src/modules/auth/`.
5
-
6
- ```txt
7
- src/shared/http/
8
- http-client.ts
9
- http-error.ts
10
- interceptors.ts
11
-
12
- src/modules/auth/
13
- auth.connector.ts
14
- auth.service.ts
15
- auth.guard.ts
16
- auth.routes.ts
17
- auth.public.ts
18
- _contracts/
19
- ```
20
-
21
- Flow pour un business module :
22
-
23
- ```txt
24
- connector -> resource/mutation -> page
25
- ```
26
-
27
- Les pages n'importent pas de DTOs et n'appellent pas `fetch()` directement. Les
28
- connectors n'importent pas la réactivité Mado ou l'UI.
29
-
30
- ## Auth Service
31
-
32
- Auth state est un ES module singleton :
33
-
34
- ```ts
35
- const _user = signal<User | null>(null);
36
- const _token = signal<string | null>(null);
37
-
38
- export const user = () => _user();
39
- export const isAuthed = computed(() => _user() !== null);
40
- ```
41
-
42
- Exposez seulement la surface nécessaire via `auth.public.ts`.
43
-
44
- ## Guards
45
-
46
- ```ts
47
- export function requireAuth(): boolean | string {
48
- if (isAuthed()) return true;
49
- return "/login";
50
- }
51
- ```
52
-
53
- Use in `src/app.routes.ts`:
54
-
55
- ```ts
56
- "/billing": layout({
57
- layout: () => import("./layouts/app-shell.layout"),
58
- guard: requireAuth,
59
- routes: billingRoutes,
60
- }),
61
- ```
62
-
63
- ## Dev Proxy
64
-
65
- ```ts
66
- export default defineConfig({
67
- plugins: [mado()],
68
- server: {
69
- proxy: { "/api": "http://localhost:3000" },
70
- },
71
- });
72
- ```
73
-
74
- Rule: `shared/http` connaît HTTP, connectors connaissent un système externe,
75
- resources connaissent les cache keys, pages connaissent l'UI, `*.public.ts` est
76
- la surface cross-module.
@@ -1,57 +0,0 @@
1
- # Déploiement
2
-
3
- Une commande, un artefact déployable :
4
-
5
- ```bash
6
- mado release
7
- ```
8
-
9
- Résultat :
10
-
11
- ```txt
12
- out/
13
- ├── index.html ← shell SPA ou HTML baked pour /
14
- ├── assets/ ← assets Vite hashés
15
- │ ├── *.gz ← gzip précompressé
16
- │ └── *.br ← brotli précompressé
17
- ├── <route>/index.html ← HTML baked pour les hébergeurs statiques
18
- ├── sitemap.xml ← sitemap à la racine du site
19
- ├── _redirects ← fallback SPA Cloudflare Pages / Netlify
20
- └── _headers ← règles de cache
21
- ```
22
-
23
- Déploie `out/` sur nginx, Cloudflare Pages, Netlify, S3/CloudFront ou GitHub
24
- Pages. Ne déploie pas `dist/` : c'est un output interne.
25
-
26
- ## Preview
27
-
28
- ```bash
29
- mado release
30
- mado preview
31
- ```
32
-
33
- `mado preview` sert le `out/` final comme un hébergeur statique : fichiers réels
34
- d'abord (`/<route>/index.html` si la route est baked), fallback SPA ensuite.
35
- Preview vérifie exactement ce qui sera déployé.
36
-
37
- ## VPS + nginx
38
-
39
- ```bash
40
- mado release
41
- rsync -avz --delete out/ user@server:/var/www/myapp/
42
- ```
43
-
44
- La recette nginx optionnelle vit dans `docs/recipes/nginx/`. Elle gère le cache
45
- immutable pour `/assets/*`, no-cache pour HTML, et le fallback SPA pour les deep
46
- links.
47
-
48
- ## Cloudflare / Netlify
49
-
50
- ```bash
51
- mado release
52
- npx wrangler pages deploy out --project-name=myapp
53
- ```
54
-
55
- `_redirects` et `_headers` sont générés automatiquement si tu n'en fournis pas.
56
- Les routes baked sont promues en vrais fichiers (`out/<route>/index.html`), donc
57
- l'hébergeur statique les sert avant le fallback SPA.
@@ -1,41 +0,0 @@
1
- # Tests
2
-
3
- Mado utilise TypeScript et les APIs du navigateur. Le dépôt du framework teste
4
- avec le test runner de Node et `linkedom`.
5
-
6
- ```bash
7
- npm run typecheck
8
- npm run build
9
- npm test
10
- ```
11
-
12
- Un test DOM minimal :
13
-
14
- ```js
15
- import test from "node:test";
16
- import assert from "node:assert/strict";
17
-
18
- const { parseHTML } = await import("linkedom");
19
- const { window } = parseHTML("<!doctype html><html><body></body></html>");
20
- globalThis.window = window;
21
- globalThis.document = window.document;
22
- globalThis.Node = window.Node;
23
- globalThis.HTMLElement = window.HTMLElement;
24
-
25
- const { html, render } = await import("../dist/src/html/template.js");
26
-
27
- test("renders", () => {
28
- const root = document.createElement("div");
29
- render(html`<p>${"hello"}</p>`, root);
30
- assert.equal(root.querySelector("p").textContent, "hello");
31
- });
32
- ```
33
-
34
- À couvrir :
35
-
36
- - signals/computed/effect : scheduling et nettoyage ;
37
- - bindings HTML : children, attributs, événements, directives ;
38
- - routes : guards, redirects, scroll/focus, error boundaries ;
39
- - formulaires : validation sync/async, races, field arrays ;
40
- - resources/mutations : clés de cache, invalidation, lifecycle ;
41
- - CLI : `mado release`, `mado bake`, `mado preview`.
@@ -1,50 +0,0 @@
1
- # Gestion des erreurs
2
-
3
- Traite les erreurs au niveau où l'utilisateur peut récupérer : routes, données,
4
- actions utilisateur.
5
-
6
- ## Routes
7
-
8
- ```ts
9
- export default routes(manifest, {
10
- errorPage: (err) => html`
11
- <main>
12
- <h1>Une erreur est survenue</h1>
13
- <pre>${err.message}</pre>
14
- <a data-link href="/">Accueil</a>
15
- </main>
16
- `,
17
- });
18
- ```
19
-
20
- `page({ errorView })` a priorité sur cette boundary globale.
21
-
22
- ## Données
23
-
24
- ```ts
25
- const users = resource(() => "/api/users", jsonFetcher<User[]>());
26
-
27
- html`
28
- ${() => users.error()
29
- ? html`<p role="alert">${users.error()!.message}</p>
30
- <button @click=${users.refresh}>Réessayer</button>`
31
- : null}
32
- `;
33
- ```
34
-
35
- ## Formulaires et mutations
36
-
37
- La validation va dans `useForm()`. Les erreurs serveur d'écriture restent près
38
- du bouton de soumission.
39
-
40
- ```ts
41
- const form = useForm(
42
- { email: { required: true, type: "email" } },
43
- { validateAsync: (values) => api.validateUser(values) },
44
- );
45
- const save = mutation((values) => api.post("/users", values), {
46
- invalidates: ["/api/users*"],
47
- });
48
- ```
49
-
50
- Nettoie les subscriptions navigateur externes avec `ctx.onDispose()`.
@@ -1,88 +0,0 @@
1
- # Bake Cookbook
2
-
3
- `mado bake` rend certaines routes en HTML statique. C'est pour le SEO et un
4
- premier rendu rapide, pas pour SSR + hydration.
5
-
6
- ## Page Minimale
7
-
8
- ```ts
9
- export default page({
10
- head: () => ({ title: "Products", description: "Catalog" }),
11
- view: ({ data }) => html`
12
- <main>
13
- <h1>Products</h1>
14
- ${data.products.map((p) => html`<article><h2>${p.name}</h2></article>`)}
15
- </main>
16
- `,
17
- bake: {
18
- paths: () => [{}],
19
- data: async () => ({ products: await api.products() }),
20
- revalidate: 3600,
21
- },
22
- });
23
- ```
24
-
25
- Dans les vues baked, préfère les tableaux simples (`items.map(...)`). Les
26
- directives runtime comme keyed `each()` sont pour le navigateur.
27
-
28
- ## Routes Dynamiques
29
-
30
- ```ts
31
- export default page<{ slug: string }>({
32
- head: ({ slug }, data) => ({ title: data.title, canonical: `/blog/${slug}` }),
33
- view: ({ data }) => html`<article>${unsafeHTML(data.html)}</article>`,
34
- bake: {
35
- paths: async () => (await api.posts()).map((p) => ({ slug: p.slug })),
36
- data: ({ slug }) => api.post(slug),
37
- },
38
- });
39
- ```
40
-
41
- Utilise `unsafeHTML()` seulement pour du HTML fiable ou déjà nettoyé.
42
-
43
- ## Route Manifest
44
-
45
- `mado bake` a besoin du manifest source :
46
-
47
- ```ts
48
- export const manifest = {
49
- "/": () => import("./pages/home.js"),
50
- "/blog/:slug": () => import("./pages/blog-post.js"),
51
- };
52
-
53
- export default routes(manifest);
54
- ```
55
-
56
- ## Output
57
-
58
- Standalone `mado bake` écrit les pages baked dans `out/baked/` par défaut.
59
- `mado release` utilise le shell de production bundlé, garde cette copie
60
- `out/baked/` pour inspection, promeut le HTML dans les vrais chemins de route
61
- dans `out/`, et copie le sitemap vers `out/sitemap.xml`.
62
-
63
- ```bash
64
- mado release
65
- tree out
66
- ```
67
-
68
- Le dossier déployable est `out/`, pas `dist/`.
69
-
70
- ## Client Boot
71
-
72
- Le HTML baked marque `#app` avec `data-mado-baked`. Ce n'est pas de
73
- l'hydration : au démarrage, `render()` remplace le DOM baked par les bindings
74
- vivants de l'application.
75
-
76
- ## Valeurs Non Supportées
77
-
78
- Bake échoue volontairement au lieu d'écrire `[object Object]`. Si une vue baked
79
- signale une directive non supportée :
80
-
81
- - remplace `each()` par `items.map(...)` dans le markup baked ;
82
- - garde les widgets interactifs dans des routes client-only ;
83
- - assure-toi que chaque valeur peut être sérialisée en HTML statique.
84
-
85
- ## Canonical Links
86
-
87
- Passe `--base-url` pour que les liens canonical et le sitemap pointent vers la
88
- production.