@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.
- package/AGENTS.md +58 -7
- package/CHANGELOG.md +121 -1
- package/README.md +21 -5
- package/dist/src/component.d.ts +2 -12
- package/dist/src/component.js +2 -29
- package/dist/src/component.js.map +1 -1
- package/dist/src/diagnostics.d.ts +0 -4
- package/dist/src/diagnostics.js +1 -0
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/html/bindings.js +3 -0
- package/dist/src/html/bindings.js.map +1 -1
- package/dist/src/html/template.js +10 -0
- package/dist/src/html/template.js.map +1 -1
- package/dist/src/resource.d.ts +3 -6
- package/dist/src/resource.js +59 -10
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/manifest.d.ts +0 -3
- package/dist/src/router/manifest.js +1 -0
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router.d.ts +1 -1
- package/dist/src/router.js +1 -1
- package/dist/src/router.js.map +1 -1
- package/dist/src/signal.d.ts +0 -4
- package/dist/src/signal.js +1 -0
- package/dist/src/signal.js.map +1 -1
- package/docs/en/02-project-layout.md +3 -2
- package/docs/en/03-static-bake.md +1 -2
- package/docs/en/06-for-backenders.md +5 -0
- package/docs/en/08-llm-zero-history-test.md +5 -0
- package/docs/en/13-deployment.md +10 -7
- package/docs/en/16-bake-cookbook.md +10 -2
- package/docs/en/18-api-freeze-map.md +63 -0
- package/docs/en/19-reactivity-ordering.md +93 -0
- package/docs/en/20-v1-stability.md +83 -0
- package/docs/en/README.md +3 -0
- package/docs/fr/02-project-layout.md +20 -13
- package/docs/fr/03-static-bake.md +1 -2
- package/docs/fr/06-for-backenders.md +6 -0
- package/docs/fr/08-llm-zero-history-test.md +5 -0
- package/docs/fr/13-deployment.md +33 -12
- package/docs/fr/16-bake-cookbook.md +57 -4
- package/docs/fr/18-api-freeze-map.md +63 -0
- package/docs/fr/19-reactivity-ordering.md +97 -0
- package/docs/fr/20-v1-stability.md +88 -0
- package/docs/fr/README.md +3 -0
- package/docs/ru/02-project-layout.md +22 -15
- package/docs/ru/03-static-bake.md +2 -3
- package/docs/ru/06-for-backenders.md +6 -0
- package/docs/ru/08-llm-zero-history-test.md +5 -0
- package/docs/ru/13-deployment.md +23 -13
- package/docs/ru/16-bake-cookbook.md +42 -8
- package/docs/ru/18-api-freeze-map.md +62 -0
- package/docs/ru/19-reactivity-ordering.md +95 -0
- package/docs/ru/20-v1-stability.md +82 -0
- package/docs/ru/README.md +3 -0
- package/docs/uk/06-for-backenders.md +5 -0
- package/docs/uk/08-llm-zero-history-test.md +5 -0
- package/docs/uk/18-api-freeze-map.md +61 -0
- package/docs/uk/19-reactivity-ordering.md +95 -0
- package/docs/uk/20-v1-stability.md +83 -0
- package/docs/uk/README.md +3 -0
- package/llms.txt +59 -5
- package/package.json +8 -3
- package/scripts/bake.mjs +4 -2
- package/scripts/cli.mjs +83 -5
- package/scripts/llm-zero-history-smoke.mjs +93 -0
- package/scripts/new.mjs +1 -1
- package/scripts/package-smoke.mjs +74 -0
- package/scripts/preview.mjs +7 -27
- package/scripts/size-budget.mjs +88 -0
- package/starters/admin/README.md +2 -2
- package/starters/admin/package.json +2 -2
- package/starters/crud/package.json +2 -2
- 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 #
|
|
8
|
-
├── tsconfig.json #
|
|
9
|
-
├──
|
|
10
|
-
├── .
|
|
11
|
-
├──
|
|
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 :
|
|
20
|
-
├── routes.ts #
|
|
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">`
|
|
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
|
package/docs/fr/13-deployment.md
CHANGED
|
@@ -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
|
-
├──
|
|
16
|
-
|
|
17
|
-
|
|
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 :
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
35
|
-
|
|
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
|
|
1
|
+
# Project Layout
|
|
2
2
|
|
|
3
3
|
Каждый new-проект на Mado имеет одинаковую структуру. Это **обязательное** соглашение.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
my-app/
|
|
7
|
-
├── package.json #
|
|
8
|
-
├── tsconfig.json #
|
|
9
|
-
├──
|
|
10
|
-
├── .
|
|
11
|
-
├──
|
|
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 # точка входа:
|
|
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/`.
|