@madojs/mado 0.9.0 → 0.10.1

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 (74) hide show
  1. package/AGENTS.md +58 -7
  2. package/CHANGELOG.md +121 -1
  3. package/README.md +21 -5
  4. package/dist/src/component.d.ts +2 -12
  5. package/dist/src/component.js +2 -29
  6. package/dist/src/component.js.map +1 -1
  7. package/dist/src/diagnostics.d.ts +0 -4
  8. package/dist/src/diagnostics.js +1 -0
  9. package/dist/src/diagnostics.js.map +1 -1
  10. package/dist/src/html/bindings.js +3 -0
  11. package/dist/src/html/bindings.js.map +1 -1
  12. package/dist/src/html/template.js +10 -0
  13. package/dist/src/html/template.js.map +1 -1
  14. package/dist/src/resource.d.ts +3 -6
  15. package/dist/src/resource.js +59 -10
  16. package/dist/src/resource.js.map +1 -1
  17. package/dist/src/router/manifest.d.ts +0 -3
  18. package/dist/src/router/manifest.js +1 -0
  19. package/dist/src/router/manifest.js.map +1 -1
  20. package/dist/src/router.d.ts +1 -1
  21. package/dist/src/router.js +1 -1
  22. package/dist/src/router.js.map +1 -1
  23. package/dist/src/signal.d.ts +0 -4
  24. package/dist/src/signal.js +1 -0
  25. package/dist/src/signal.js.map +1 -1
  26. package/docs/en/02-project-layout.md +3 -2
  27. package/docs/en/03-static-bake.md +1 -2
  28. package/docs/en/06-for-backenders.md +5 -0
  29. package/docs/en/08-llm-zero-history-test.md +5 -0
  30. package/docs/en/13-deployment.md +10 -7
  31. package/docs/en/16-bake-cookbook.md +10 -2
  32. package/docs/en/18-api-freeze-map.md +63 -0
  33. package/docs/en/19-reactivity-ordering.md +93 -0
  34. package/docs/en/20-v1-stability.md +83 -0
  35. package/docs/en/README.md +3 -0
  36. package/docs/fr/02-project-layout.md +20 -13
  37. package/docs/fr/03-static-bake.md +1 -2
  38. package/docs/fr/06-for-backenders.md +6 -0
  39. package/docs/fr/08-llm-zero-history-test.md +5 -0
  40. package/docs/fr/13-deployment.md +33 -12
  41. package/docs/fr/16-bake-cookbook.md +57 -4
  42. package/docs/fr/18-api-freeze-map.md +63 -0
  43. package/docs/fr/19-reactivity-ordering.md +97 -0
  44. package/docs/fr/20-v1-stability.md +88 -0
  45. package/docs/fr/README.md +3 -0
  46. package/docs/ru/02-project-layout.md +22 -15
  47. package/docs/ru/03-static-bake.md +2 -3
  48. package/docs/ru/06-for-backenders.md +6 -0
  49. package/docs/ru/08-llm-zero-history-test.md +5 -0
  50. package/docs/ru/13-deployment.md +23 -13
  51. package/docs/ru/16-bake-cookbook.md +42 -8
  52. package/docs/ru/18-api-freeze-map.md +62 -0
  53. package/docs/ru/19-reactivity-ordering.md +95 -0
  54. package/docs/ru/20-v1-stability.md +82 -0
  55. package/docs/ru/README.md +3 -0
  56. package/docs/uk/06-for-backenders.md +5 -0
  57. package/docs/uk/08-llm-zero-history-test.md +5 -0
  58. package/docs/uk/18-api-freeze-map.md +61 -0
  59. package/docs/uk/19-reactivity-ordering.md +95 -0
  60. package/docs/uk/20-v1-stability.md +83 -0
  61. package/docs/uk/README.md +3 -0
  62. package/llms.txt +59 -5
  63. package/package.json +8 -3
  64. package/scripts/bake.mjs +4 -2
  65. package/scripts/cli.mjs +83 -5
  66. package/scripts/llm-zero-history-smoke.mjs +93 -0
  67. package/scripts/new.mjs +1 -1
  68. package/scripts/package-smoke.mjs +74 -0
  69. package/scripts/preview.mjs +7 -27
  70. package/scripts/size-budget.mjs +88 -0
  71. package/starters/admin/README.md +2 -2
  72. package/starters/admin/package.json +2 -2
  73. package/starters/crud/package.json +2 -2
  74. package/starters/minimal/package.json +2 -2
@@ -0,0 +1,83 @@
1
+ # v1 stability
2
+
3
+ > What Mado promises after v1, and what remains free to evolve.
4
+
5
+ Mado v1 means the public app-facing contract is stable enough for real
6
+ business apps. It does not mean every internal file, generated byte, starter
7
+ copy, or diagnostic string is frozen forever.
8
+
9
+ Read this together with:
10
+
11
+ - [API freeze map](./18-api-freeze-map.md)
12
+ - [Reactivity ordering](./19-reactivity-ordering.md)
13
+
14
+ ## Stable under SemVer
15
+
16
+ After v1, Mado treats these as SemVer-protected:
17
+
18
+ - Public exports from `@madojs/mado`.
19
+ - Public TypeScript types exported from `@madojs/mado`.
20
+ - The `@madojs/mado/devtools.js` side-effect subpath.
21
+ - Template binding syntax: child `${}`, `@event`, `.prop`, `?boolean`,
22
+ attribute bindings, directives and `each()`.
23
+ - Signal semantics documented in the reactivity ordering guide.
24
+ - Component lifecycle semantics: setup once per connection lifetime, deferred
25
+ teardown for same-tick moves, cleanup via `ctx.onDispose`.
26
+ - Router/page/resource/form contracts documented in the English docs.
27
+ - CLI command names and broad command intent (`build`, `dev`, `release`,
28
+ `bake`, `bundle`, `preview`, `init`, `new`).
29
+
30
+ Breaking these requires a major version.
31
+
32
+ ## Allowed in minor releases
33
+
34
+ Minor releases may add:
35
+
36
+ - New root exports.
37
+ - New options on existing APIs.
38
+ - New diagnostics and warnings.
39
+ - New starters, examples, docs and CLI flags.
40
+ - Performance improvements and internal implementation rewrites.
41
+
42
+ Minor releases should not require existing correct apps to change code.
43
+
44
+ ## Allowed in patch releases
45
+
46
+ Patch releases may fix bugs, tighten diagnostics, improve docs, and make
47
+ compatible implementation changes. A patch may change timing only when the old
48
+ timing was an undocumented bug and the change preserves the documented
49
+ reactivity ordering contract.
50
+
51
+ ## Not stable
52
+
53
+ These are intentionally not SemVer-protected:
54
+
55
+ - Internal package subpaths other than `@madojs/mado/devtools.js`.
56
+ - Files under `src/`, `dist/src/`, and implementation module boundaries.
57
+ - `_testHooks`, diagnostics internals and warning codes.
58
+ - Exact generated JavaScript text, chunk names, sourcemap content and bundle
59
+ byte layout.
60
+ - Internal parser, binding, router and resource cache data structures.
61
+ - Starter app visual copy and demo data.
62
+
63
+ Apps should not import internal files or assert exact bundle output.
64
+
65
+ ## Bundle and release output
66
+
67
+ Mado will keep a size budget and deterministic release tests, but v1 stability
68
+ does not freeze byte-for-byte bundler output. Hashes, chunk boundaries and
69
+ generated asset names may change as long as the documented deployment contract
70
+ continues to work.
71
+
72
+ ## If a release breaks you
73
+
74
+ If an update breaks code that uses only public exports and documented behaviour,
75
+ treat it as a bug. Open an issue with:
76
+
77
+ - the Mado version before and after;
78
+ - the public API involved;
79
+ - a minimal reproduction;
80
+ - whether the break is runtime behaviour, TypeScript types, CLI output or docs.
81
+
82
+ If the break depends on an internal subpath or exact generated output, it may
83
+ still be worth reporting, but it is not considered a SemVer break.
package/docs/en/README.md CHANGED
@@ -22,3 +22,6 @@ English documentation set.
22
22
  | Error handling | [15-error-handling.md](./15-error-handling.md) |
23
23
  | Bake cookbook | [16-bake-cookbook.md](./16-bake-cookbook.md) |
24
24
  | Shadow DOM + Forms | [17-shadow-dom-forms.md](./17-shadow-dom-forms.md) |
25
+ | API freeze map | [18-api-freeze-map.md](./18-api-freeze-map.md) |
26
+ | Reactivity ordering | [19-reactivity-ordering.md](./19-reactivity-ordering.md) |
27
+ | v1 stability | [20-v1-stability.md](./20-v1-stability.md) |
@@ -4,20 +4,14 @@ Chaque nouveau projet Mado a la même structure. C'est une convention **obligato
4
4
 
5
5
  ```
6
6
  my-app/
7
- ├── package.json # exactement 1 dép : typescript (esbuild optionnel)
8
- ├── tsconfig.json # avec paths "@madojs/mado" import sans chemins relatifs
9
- ├── Dockerfile + nginx.conf # copiés depuis Mado/ lors du scaffold
10
- ├── .gitlab-ci.yml | .github/workflows/ci.yml
11
- ├── server/serve.mjs # dev-server de Mado, sans dépendances
12
- ├── scripts/
13
- │ ├── bundle.mjs # bundle de production esbuild
14
- │ └── new.mjs # générateur de pages
15
- ├── templates/ # templates pour new.mjs
16
- ├── docs/ # documentation du projet (vous pouvez copier nos guides)
17
- ├── public/ # assets statiques (favicon, manifests)
7
+ ├── package.json # runtime dep: @madojs/mado
8
+ ├── tsconfig.json # strict TS, ES2022, Bundler resolution
9
+ ├── mado.config.json # configuration dev/build/bake/bundle
10
+ ├── index.html # shell SPA et template pour bake
11
+ ├── public/ # assets statiques (favicon, images, robots.txt)
18
12
  └── src/
19
- ├── main.ts # entrée : providers + montage de <x-app>
20
- ├── routes.ts # manifeste de routes
13
+ ├── main.ts # entrée : mount router dans #app
14
+ ├── routes.ts # route manifest (default + named manifest)
21
15
  ├── pages/ # une page = un fichier = `export default page({...})`
22
16
  ├── components/ # composants réutilisables (x-*)
23
17
  ├── layouts/ # pages de layout (pour nested)
@@ -28,6 +22,19 @@ my-app/
28
22
  └── ... # utilitaires, types, règles métier
29
23
  ```
30
24
 
25
+ ## États Des Artefacts
26
+
27
+ | Dossier | Ce que c'est | Écrit par | Déployer ? |
28
+ |---|---|---|---|
29
+ | `src/` | sources TypeScript | vous | non |
30
+ | `dist/` | output `tsc`, native ESM pour dev | `mado build` | non |
31
+ | `public/` | assets statiques écrits par vous | vous | via `out/` |
32
+ | `out/` | artefact déployable : shell SPA + bundles + HTML baked promu | `mado release` | oui |
33
+
34
+ `mado release` = `typecheck` + `build` (`dist/`) + `bundle`
35
+ (`out/assets/`) + `bake` (`out/baked/`) + promotion du HTML baked et de
36
+ `sitemap.xml` dans les chemins déployables de `out/` + copie de `public/*`.
37
+
31
38
  ## Où mettre un nouveau fichier ?
32
39
 
33
40
  | Quoi | Où |
@@ -148,7 +148,6 @@ out/
148
148
  {"@context":"https://schema.org","@type":"Product","..."}
149
149
  </script>
150
150
  <meta name="bake-revalidate" content="3600" data-mado-head="baked">
151
- <meta name="bake-stamp" content="1234567890" data-mado-head="baked">
152
151
  </head>
153
152
  <body>
154
153
  <div id="app">
@@ -231,7 +230,7 @@ export default page<{ slug: string }>({
231
230
 
232
231
  ## Revalidate / CDN
233
232
 
234
- `bake.revalidate: 3600` écrit `<meta name="bake-revalidate" content="3600">` et `bake-stamp`
233
+ `bake.revalidate: 3600` écrit `<meta name="bake-revalidate" content="3600">`
235
234
  dans le HTML. C'est des **métadonnées** — le framework ne re-bake rien lui-même. Stratégies :
236
235
 
237
236
  1. **Option la plus simple** : cron dans CI — `npm run bake && rsync out/ origin:/var/www/`.
@@ -154,6 +154,12 @@ await save.run(newUser);
154
154
  // automatiquement : user.data() se mettra à jour si le glob correspond
155
155
  ```
156
156
 
157
+ Les clés de `resource()` sont l'identité du cache. Incluez l'endpoint, les query
158
+ params et la forme des données dans la clé : deux `resource()` vivants avec la
159
+ même clé partagent le cache et la requête in-flight. Si la même clé est utilisée
160
+ avec un fetcher différent, Mado avertit, car cela signifie généralement que la
161
+ clé de cache est trop large.
162
+
157
163
  Si une telle abstraction existait dans le monde Go pour les caches côté serveur — on
158
164
  pleurerait tous de joie.
159
165
 
@@ -53,6 +53,11 @@ Cherchez ces éléments après l'implémentation :
53
53
  L'implémentation actuelle de `examples/tickets` n'a pas nécessité de nouvelles API publiques ni
54
54
  de dépendances runtime.
55
55
 
56
+ CI exécute `npm run llm:smoke` comme proxy déterministe pour cette tâche :
57
+ il vérifie que `llms.txt` contient toujours les règles clés, compare l'artefact
58
+ commité `examples/tickets` à la surface API Mado requise et aux failure
59
+ patterns, puis build le projet et lance `test/tickets-smoke.test.mjs`.
60
+
56
61
  Le principal point de pression dans la documentation reste le lifecycle : les anciens exemples
57
62
  peuvent donner l'impression qu'il est acceptable de créer `resource()` directement dans
58
63
  `page.view()`. L'exemple tickets utilise plutôt des composants wrapper au niveau page, de sorte
@@ -1,6 +1,6 @@
1
1
  # Déploiement
2
2
 
3
- Une commande, un artefact :
3
+ Une commande, un artefact déployable :
4
4
 
5
5
  ```bash
6
6
  mado release
@@ -10,30 +10,51 @@ Résultat :
10
10
 
11
11
  ```txt
12
12
  out/
13
- ├── index.html
14
- ├── assets/
15
- ├── baked/
16
- ├── _redirects
17
- └── _headers
13
+ ├── index.html ← shell SPA ou HTML baked promu pour /
14
+ ├── assets/ ← bundles hashés (main-ABC.js, chunk-XYZ.js, ...)
15
+ ├── *.gz ← gzip précompressé
16
+ │ └── *.br ← brotli précompressé
17
+ ├── baked/ ← copie de bake pour inspection/debugging
18
+ │ ├── <route>/index.html
19
+ │ └── sitemap.xml
20
+ ├── <route>/index.html ← HTML baked promu pour les hébergeurs statiques
21
+ ├── sitemap.xml ← sitemap à la racine du site
22
+ ├── _redirects ← fallback SPA Cloudflare Pages / Netlify
23
+ └── _headers ← règles de cache
18
24
  ```
19
25
 
20
26
  Déploie `out/` sur nginx, Cloudflare Pages, Netlify, S3/CloudFront ou GitHub
21
- Pages.
27
+ Pages. Ne déploie pas `dist/` : c'est un output interne.
28
+
29
+ ## Preview
22
30
 
23
31
  ```bash
24
32
  mado release
25
33
  mado preview
26
34
  ```
27
35
 
28
- `mado preview` sert `out/` comme un hébergeur statique : HTML baked d'abord,
29
- fallback SPA ensuite.
36
+ `mado preview` sert le `out/` final comme un hébergeur statique : fichiers réels
37
+ d'abord (`/<route>/index.html` si la route est baked), fallback SPA ensuite.
38
+ Preview ne fait plus de mapping virtuel depuis `out/baked/`, donc il vérifie
39
+ exactement ce qui sera déployé.
30
40
 
31
- Pour VPS + nginx :
41
+ ## VPS + nginx
32
42
 
33
43
  ```bash
34
44
  mado release
35
45
  rsync -avz --delete out/ user@server:/var/www/myapp/
36
46
  ```
37
47
 
38
- Le `nginx.conf` fourni gère cache immutable pour les bundles hashés, no-cache
39
- pour HTML, et fallback SPA pour les deep links.
48
+ Le `nginx.conf` fourni gère le cache immutable pour les bundles hashés, no-cache
49
+ pour HTML, et le fallback SPA pour les deep links.
50
+
51
+ ## Cloudflare / Netlify
52
+
53
+ ```bash
54
+ mado release
55
+ npx wrangler pages deploy out --project-name=myapp
56
+ ```
57
+
58
+ `_redirects` et `_headers` sont générés automatiquement si tu n'en fournis pas.
59
+ Les routes baked sont promues en vrais fichiers (`out/<route>/index.html`), donc
60
+ l'hébergeur statique les sert avant le fallback SPA.
@@ -1,8 +1,10 @@
1
- # Bake cookbook
1
+ # Bake Cookbook
2
2
 
3
3
  `mado bake` rend certaines routes en HTML statique. C'est pour le SEO et un
4
4
  premier rendu rapide, pas pour SSR + hydration.
5
5
 
6
+ ## Page Minimale
7
+
6
8
  ```ts
7
9
  export default page({
8
10
  head: () => ({ title: "Products", description: "Catalog" }),
@@ -21,15 +23,66 @@ export default page({
21
23
  ```
22
24
 
23
25
  Dans les vues baked, préfère les tableaux simples (`items.map(...)`). Les
24
- directives runtime comme `each()` sont pour le navigateur.
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 :
25
46
 
26
47
  ```ts
27
48
  export const manifest = {
28
49
  "/": () => import("./pages/home.js"),
29
50
  "/blog/:slug": () => import("./pages/blog-post.js"),
30
51
  };
52
+
31
53
  export default routes(manifest);
32
54
  ```
33
55
 
34
- `mado release` produit l'artefact déployable dans `out/`. Si bake signale une
35
- valeur non supportée, remplace la partie runtime-only ou rends-la côté client.
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` ou configure `bake.baseUrl` dans `mado.config.json` pour que
88
+ les liens canonical et le sitemap pointent vers la production.
@@ -0,0 +1,63 @@
1
+ # Carte de gel de l'API
2
+
3
+ > Ce qui est public, ce qui est interne, et ce que SemVer protégera en v1.
4
+
5
+ Le contrat v1 de Mado est volontairement petit. Le code applicatif importe
6
+ depuis la racine du package :
7
+
8
+ ```ts
9
+ import { component, html, resource, routes, signal } from "@madojs/mado";
10
+ ```
11
+
12
+ Le seul subpath public est le module side-effect devtools :
13
+
14
+ ```ts
15
+ import "@madojs/mado/devtools.js";
16
+ ```
17
+
18
+ Tout le reste sous `dist/src/` est un détail d'implémentation, même si le
19
+ fichier est visible dans le dépôt.
20
+
21
+ ## API publique stable
22
+
23
+ Ces noms sont publics et protégés par SemVer une fois v1 publiée :
24
+
25
+ - Réactivité : `signal`, `computed`, `effect`, `untracked`, `batch`,
26
+ `flushSync`.
27
+ - Templates et directives : `html`, `render`, `each`, `list`, `unsafeHTML`,
28
+ `ref`, `classMap`, `styleMap`.
29
+ - Composants et CSS : `component`, `css`, `cssVars`.
30
+ - Routage et pages : `routes`, `router`, `page`, `layout`, `nested`,
31
+ `navigate`, `queryParam`, `prefetchPath`.
32
+ - Data : `resource`, `mutation`, `invalidate`, `jsonFetcher`, `HttpError`.
33
+ - Formulaires : `useForm`.
34
+ - Head et persistence : `applyHead`, `persisted`.
35
+ - Context : `createContext`, `provide`, `inject`.
36
+ - Helpers lifecycle avancés : `createLifecycle`, `runInLifecycle`,
37
+ `getCurrentLifecycle`.
38
+ - Types TypeScript publics exportés depuis `@madojs/mado`.
39
+
40
+ ## Interne ou instable
41
+
42
+ Ce n'est pas de l'API publique :
43
+
44
+ - Subpaths du package autres que `@madojs/mado` et
45
+ `@madojs/mado/devtools.js`.
46
+ - Internals du parser/binding comme `html/parser.js`, `html/bindings.js`,
47
+ `ChildState` et `EachEntry`.
48
+ - Internals du routeur comme `router/match.js`, `router/navigation.js` et
49
+ `router/manifest.js`.
50
+ - Internals de diagnostics et tous les `_testHooks`.
51
+ - Texte exact du bundle généré, noms des chunks et layout interne des fichiers.
52
+
53
+ Les tests du dépôt peuvent importer des fichiers internes via des chemins
54
+ relatifs `dist/`. Le code applicatif ne doit pas le faire.
55
+
56
+ ## Ce qui peut changer
57
+
58
+ Les patch et minor releases peuvent ajouter des root exports, options,
59
+ diagnostics, docs ou starters. Elles peuvent aussi changer les internals, la
60
+ forme du bundle et les détails d'implémentation tant que l'API stable et le
61
+ comportement documenté restent compatibles.
62
+
63
+ Les changements cassants de l'API stable nécessitent une version majeure.
@@ -0,0 +1,97 @@
1
+ # Ordre de la réactivité
2
+
3
+ > Le petit ensemble de garanties d'ordre que Mado traite comme comportement public.
4
+
5
+ La réactivité de Mado est synchrone pour les lectures et planifiée pour les
6
+ side effects. Le but est une mise à jour UI prévisible plutôt qu'un grand modèle
7
+ de scheduling.
8
+
9
+ ## Signals
10
+
11
+ `signal(value)` renvoie une fonction getter. `set(next)` change la valeur
12
+ immédiatement sauf si `Object.is(previous, next)` vaut `true`.
13
+
14
+ ```ts
15
+ const count = signal(0);
16
+ count.set(1);
17
+ count(); // 1, immédiatement
18
+ ```
19
+
20
+ Les computed values sont marquées avant l'exécution des effects : un effect qui
21
+ lit un computed observe les dépendances courantes, pas un cache obsolète.
22
+
23
+ ## Effects
24
+
25
+ `effect(fn)` s'exécute une première fois immédiatement. Les changements
26
+ ultérieurs de dépendances planifient une seule exécution en microtask. Les tests
27
+ peuvent appeler `flushSync()` pour vider cette file de façon synchrone.
28
+
29
+ Si un effect retourne une fonction de cleanup, Mado l'exécute avant l'exécution
30
+ suivante de l'effect et à nouveau quand le disposer est appelé.
31
+
32
+ ```ts
33
+ const stop = effect(() => {
34
+ const id = setInterval(tick, 1000);
35
+ return () => clearInterval(id);
36
+ });
37
+
38
+ stop();
39
+ ```
40
+
41
+ Dans les composants et pages, préférez `ctx.onDispose()` / page `onDispose()`
42
+ pour le cleanup à l'unmount. Le cleanup d'un effect est un cleanup par run.
43
+
44
+ ## Batch
45
+
46
+ `batch(fn)` regroupe les écritures de signals en un seul passage des
47
+ subscribers. Les effects ne s'exécutent pas avant la sortie du batch le plus
48
+ extérieur, y compris avec des batches imbriqués.
49
+
50
+ ```ts
51
+ batch(() => {
52
+ first.set("Ada");
53
+ batch(() => last.set("Lovelace"));
54
+ });
55
+ // les effects ne voient que la paire finale
56
+ ```
57
+
58
+ Les `computed({ equals })` observés préservent aussi l'atomicité du batch : ils
59
+ se recalculent une fois après le batch extérieur, sur l'état entièrement
60
+ appliqué. Ils ne doivent pas observer un batch à moitié appliqué comme
61
+ `(new x, old y)`.
62
+
63
+ ## Mises à jour DOM
64
+
65
+ `render(result, container)` réutilise l'instance de template existante quand le
66
+ render suivant a les mêmes template strings. Pour les child bindings qui
67
+ retournent un `html``` imbriqué, la même règle s'applique : mêmes strings =
68
+ mise à jour sur place, autres strings = reconstruction de cette branche.
69
+
70
+ Ainsi, des changements de signals sans rapport ne recréent pas un `<input>`
71
+ dans un template imbriqué stable : focus, état DOM et listeners survivent.
72
+
73
+ Les listes doivent utiliser `each(items, key, renderItem)`. Les keys définissent
74
+ l'identité DOM. Les duplicate keys avertissent en development et retombent sur
75
+ un suffixe positionnel pour que chaque item soit rendu, mais les duplicate keys
76
+ sont un bug de données.
77
+
78
+ ## Teardown des composants
79
+
80
+ Les custom elements peuvent recevoir `disconnectedCallback()` puis
81
+ `connectedCallback()` pendant un déplacement dans le même tick. Mado diffère le
82
+ teardown du composant jusqu'à une microtask et l'annule si l'élément est
83
+ reconnecté, donc les reorders keyed préservent l'état du composant. Une vraie
84
+ suppression lance tout de même le cleanup lifecycle à la microtask suivante.
85
+
86
+ ## Non garanti
87
+
88
+ Mado ne garantit pas le nombre exact de microtasks internes du scheduler,
89
+ l'ordre des effects indépendants sans dépendances communes, la forme du bundle
90
+ généré ni le layout interne des modules. Ce sont des détails d'implémentation.
91
+
92
+ Les tests invariants de ce contrat vivent dans :
93
+
94
+ - `test/reactivity-ordering.test.mjs`
95
+ - `test/signal-batch-equals.test.mjs`
96
+ - `test/update-nested-reuse.test.mjs`
97
+ - `test/each-component-state.test.mjs`
@@ -0,0 +1,88 @@
1
+ # Stabilité v1
2
+
3
+ > Ce que Mado promet après v1, et ce qui reste libre d'évoluer.
4
+
5
+ Mado v1 signifie que le contrat public côté application est assez stable pour
6
+ de vraies applications métier. Cela ne veut pas dire que chaque fichier interne,
7
+ octet généré, starter copy ou diagnostic string est gelé pour toujours.
8
+
9
+ À lire avec :
10
+
11
+ - [Carte de gel de l'API](./18-api-freeze-map.md)
12
+ - [Ordre de la réactivité](./19-reactivity-ordering.md)
13
+
14
+ ## Stable sous SemVer
15
+
16
+ Après v1, Mado considère comme protégés par SemVer :
17
+
18
+ - Les exports publics de `@madojs/mado`.
19
+ - Les types TypeScript publics exportés depuis `@madojs/mado`.
20
+ - Le subpath side-effect `@madojs/mado/devtools.js`.
21
+ - La syntaxe de template binding : child `${}`, `@event`, `.prop`,
22
+ `?boolean`, attribute bindings, directives et `each()`.
23
+ - Les semantics des signals documentées dans le guide d'ordre de réactivité.
24
+ - Les semantics du lifecycle composant : setup une fois par connection
25
+ lifetime, teardown différé pour les same-tick moves, cleanup via
26
+ `ctx.onDispose`.
27
+ - Les contrats router/page/resource/form documentés dans les docs anglaises.
28
+ - Les noms de commandes CLI et leur intention générale (`build`, `dev`,
29
+ `release`, `bake`, `bundle`, `preview`, `init`, `new`).
30
+
31
+ Casser cela nécessite une version majeure.
32
+
33
+ ## Autorisé en minor releases
34
+
35
+ Les minor releases peuvent ajouter :
36
+
37
+ - De nouveaux root exports.
38
+ - De nouvelles options sur des API existantes.
39
+ - De nouveaux diagnostics et warnings.
40
+ - De nouveaux starters, examples, docs et flags CLI.
41
+ - Des améliorations de performance et des rewrites internes.
42
+
43
+ Une minor release ne devrait pas forcer les apps correctes existantes à changer
44
+ leur code.
45
+
46
+ ## Autorisé en patch releases
47
+
48
+ Les patch releases peuvent corriger des bugs, durcir les diagnostics, améliorer
49
+ les docs et faire des changements d'implémentation compatibles. Un patch peut
50
+ changer le timing seulement si l'ancien timing était un bug non documenté et
51
+ que le changement conserve le contrat d'ordre de réactivité.
52
+
53
+ ## Non stable
54
+
55
+ Ne sont volontairement pas protégés par SemVer :
56
+
57
+ - Les subpaths internes du package autres que `@madojs/mado/devtools.js`.
58
+ - Les fichiers sous `src/`, `dist/src/` et les frontières de modules
59
+ d'implémentation.
60
+ - `_testHooks`, internals de diagnostics et warning codes.
61
+ - Le JavaScript exact généré, les noms de chunks, le contenu sourcemap et le
62
+ byte layout du bundle.
63
+ - Les structures internes du parser, des bindings, du routeur et du cache
64
+ resource.
65
+ - Le texte visuel et les données de démonstration des starters.
66
+
67
+ Les apps ne doivent pas importer de fichiers internes ni vérifier l'output exact
68
+ du bundle.
69
+
70
+ ## Bundle et output de release
71
+
72
+ Mado gardera un size budget et des tests de release déterministe, mais la
73
+ stabilité v1 ne fige pas l'output du bundler octet par octet. Les hashes,
74
+ frontières de chunks et noms d'assets générés peuvent changer tant que le
75
+ contrat de déploiement documenté continue de fonctionner.
76
+
77
+ ## Si une release vous casse
78
+
79
+ Si une mise à jour casse du code qui utilise seulement les exports publics et le
80
+ comportement documenté, traitez-le comme un bug. Ouvrez une issue avec :
81
+
82
+ - la version de Mado avant et après ;
83
+ - l'API publique impliquée ;
84
+ - une reproduction minimale ;
85
+ - si la casse concerne le runtime, les types TypeScript, l'output CLI ou les docs.
86
+
87
+ Si la casse dépend d'un subpath interne ou de l'output généré exact, cela peut
88
+ quand même valoir un rapport, mais ce n'est pas considéré comme une casse SemVer.
package/docs/fr/README.md CHANGED
@@ -22,3 +22,6 @@ Documentation française.
22
22
  | Gestion des erreurs | [15-error-handling.md](./15-error-handling.md) |
23
23
  | Guide de recettes bake | [16-bake-cookbook.md](./16-bake-cookbook.md) |
24
24
  | Shadow DOM + formulaires | [17-shadow-dom-forms.md](./17-shadow-dom-forms.md) |
25
+ | Carte de gel de l'API | [18-api-freeze-map.md](./18-api-freeze-map.md) |
26
+ | Ordre de la réactivité | [19-reactivity-ordering.md](./19-reactivity-ordering.md) |
27
+ | Stabilité v1 | [20-v1-stability.md](./20-v1-stability.md) |
@@ -1,23 +1,17 @@
1
- # Project layout
1
+ # Project Layout
2
2
 
3
3
  Каждый new-проект на Mado имеет одинаковую структуру. Это **обязательное** соглашение.
4
4
 
5
5
  ```
6
6
  my-app/
7
- ├── package.json # ровно 1 dep: typescript (esbuild опц.)
8
- ├── tsconfig.json # с paths "@madojs/mado" импорт без относительных путей
9
- ├── Dockerfile + nginx.conf # копируем из Mado/ при scaffold
10
- ├── .gitlab-ci.yml | .github/workflows/ci.yml
11
- ├── server/serve.mjs # dev-сервер из Mado, без deps
12
- ├── scripts/
13
- │ ├── bundle.mjs # esbuild прод-бандл
14
- │ └── new.mjs # скаффолд страницы
15
- ├── templates/ # шаблоны для new.mjs
16
- ├── docs/ # проектные доки (можно копировать наши гайды)
17
- ├── public/ # статика (favicon, манифесты)
7
+ ├── package.json # runtime dep: @madojs/mado
8
+ ├── tsconfig.json # strict TS, ES2022, Bundler resolution
9
+ ├── mado.config.json # dev/build/bake/bundle config
10
+ ├── index.html # SPA shell и template для bake
11
+ ├── public/ # статика (favicon, images, robots.txt)
18
12
  └── src/
19
- ├── main.ts # точка входа: провайдеры + монтаж <x-app>
20
- ├── routes.ts # манифест роутов
13
+ ├── main.ts # точка входа: mount router в #app
14
+ ├── routes.ts # route manifest (default + named manifest)
21
15
  ├── pages/ # одна страница = один файл = `export default page({...})`
22
16
  ├── components/ # переиспользуемые компоненты (x-*)
23
17
  ├── layouts/ # layout-страницы (для nested)
@@ -28,6 +22,19 @@ my-app/
28
22
  └── ... # утилиты, типы, бизнес-правила
29
23
  ```
30
24
 
25
+ ## Artifact States
26
+
27
+ | Folder | Что это | Кто пишет | Deploy? |
28
+ |---|---|---|---|
29
+ | `src/` | исходники TypeScript | ты | no |
30
+ | `dist/` | output `tsc`, native ESM для dev | `mado build` | no |
31
+ | `public/` | авторская статика | ты | через `out/` |
32
+ | `out/` | deploy artifact: SPA shell + bundles + promoted baked HTML | `mado release` | yes |
33
+
34
+ `mado release` = `typecheck` + `build` (`dist/`) + `bundle`
35
+ (`out/assets/`) + `bake` (`out/baked/`) + promote baked HTML и
36
+ `sitemap.xml` в deployable `out/` paths + copy `public/*`.
37
+
31
38
  ## Куда положить новый файл?
32
39
 
33
40
  | Что | Куда |
@@ -54,4 +61,4 @@ my-app/
54
61
 
55
62
  - ❌ Конфиги билдеров (webpack, rollup, vite) — у нас их нет.
56
63
  - ❌ `.env`-файлы — env читается из `process.env`/`import.meta.env` в `lib/config.ts`.
57
- - ❌ Тесты вперемешку с кодом — все в `test/`.
64
+ - ❌ Тесты вперемешку с кодом — все в `test/`.