@madojs/mado 0.10.0 → 0.11.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.
- package/AGENTS.md +24 -26
- package/CHANGELOG.md +98 -0
- package/README.md +18 -45
- package/TODO.md +52 -48
- package/dist/src/component.d.ts +2 -1
- package/dist/src/component.js +5 -2
- package/dist/src/component.js.map +1 -1
- package/dist/src/each.d.ts +1 -1
- package/dist/src/each.js +1 -1
- package/dist/src/each.js.map +1 -1
- package/dist/src/html/template.js +10 -0
- package/dist/src/html/template.js.map +1 -1
- package/dist/src/index.d.ts +11 -6
- package/dist/src/index.js +5 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/lazy.d.ts +1 -1
- package/dist/src/lazy.js +1 -1
- package/dist/src/lazy.js.map +1 -1
- package/dist/src/page.d.ts +17 -21
- package/dist/src/page.js +7 -12
- package/dist/src/page.js.map +1 -1
- package/dist/src/router/manifest.d.ts +1 -1
- package/dist/src/router/manifest.js +21 -13
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/match.d.ts +2 -2
- package/dist/src/router/match.js +3 -3
- package/dist/src/router/match.js.map +1 -1
- package/dist/src/router/navigation.js +1 -1
- package/dist/src/router/navigation.js.map +1 -1
- package/dist/src/vite/index.d.ts +10 -0
- package/dist/src/vite/index.js +33 -0
- package/dist/src/vite/index.js.map +1 -0
- package/docs/en/00-the-mado-way.md +25 -12
- package/docs/en/01-routing.md +90 -142
- package/docs/en/02-project-layout.md +59 -52
- package/docs/en/03-static-bake.md +5 -6
- package/docs/en/05-why-mado.md +6 -6
- package/docs/en/06-for-backenders.md +18 -22
- package/docs/en/08-llm-zero-history-test.md +9 -14
- package/docs/en/09-shadow-vs-light-dom.md +28 -36
- package/docs/en/10-app-architecture.md +158 -96
- package/docs/en/11-layouts.md +22 -24
- package/docs/en/12-auth-and-api.md +89 -182
- package/docs/en/13-deployment.md +25 -26
- package/docs/en/14-testing.md +4 -4
- package/docs/en/16-bake-cookbook.md +17 -10
- package/docs/en/18-api-freeze-map.md +6 -4
- package/docs/en/20-v1-stability.md +1 -1
- package/docs/fr/00-the-mado-way.md +55 -90
- package/docs/fr/01-routing.md +70 -152
- package/docs/fr/02-project-layout.md +74 -48
- package/docs/fr/03-static-bake.md +1 -1
- package/docs/fr/05-why-mado.md +6 -6
- package/docs/fr/06-for-backenders.md +7 -7
- package/docs/fr/08-llm-zero-history-test.md +21 -48
- package/docs/fr/09-shadow-vs-light-dom.md +43 -162
- package/docs/fr/10-app-architecture.md +110 -33
- package/docs/fr/11-layouts.md +24 -12
- package/docs/fr/12-auth-and-api.md +63 -22
- package/docs/fr/13-deployment.md +30 -12
- package/docs/fr/14-testing.md +1 -1
- package/docs/fr/16-bake-cookbook.md +57 -4
- package/docs/fr/18-api-freeze-map.md +1 -1
- package/docs/fr/20-v1-stability.md +1 -1
- package/docs/recipes/nginx/README.md +13 -0
- package/docs/ru/00-the-mado-way.md +53 -75
- package/docs/ru/01-routing.md +68 -143
- package/docs/ru/02-project-layout.md +75 -48
- package/docs/ru/03-static-bake.md +2 -2
- package/docs/ru/05-why-mado.md +6 -6
- package/docs/ru/06-for-backenders.md +7 -7
- package/docs/ru/08-llm-zero-history-test.md +9 -14
- package/docs/ru/09-shadow-vs-light-dom.md +43 -178
- package/docs/ru/10-app-architecture.md +115 -63
- package/docs/ru/11-layouts.md +24 -24
- package/docs/ru/12-auth-and-api.md +57 -35
- package/docs/ru/13-deployment.md +19 -13
- package/docs/ru/14-testing.md +1 -1
- package/docs/ru/16-bake-cookbook.md +48 -8
- package/docs/ru/18-api-freeze-map.md +5 -3
- package/docs/ru/20-v1-stability.md +1 -1
- package/docs/uk/00-the-mado-way.md +70 -44
- package/docs/uk/01-routing.md +41 -47
- package/docs/uk/02-project-layout.md +68 -41
- package/docs/uk/03-static-bake.md +1 -2
- package/docs/uk/06-for-backenders.md +3 -3
- package/docs/uk/08-llm-zero-history-test.md +22 -24
- package/docs/uk/09-shadow-vs-light-dom.md +37 -86
- package/docs/uk/10-app-architecture.md +72 -31
- package/docs/uk/11-layouts.md +25 -12
- package/docs/uk/12-auth-and-api.md +58 -22
- package/docs/uk/13-deployment.md +4 -3
- package/docs/uk/14-testing.md +1 -1
- package/docs/uk/18-api-freeze-map.md +1 -1
- package/docs/uk/20-v1-stability.md +1 -1
- package/llms.txt +14 -15
- package/package.json +18 -11
- package/scripts/_config.mjs +15 -161
- package/scripts/bake.mjs +71 -58
- package/scripts/cli/generate.mjs +348 -0
- package/scripts/cli/help.mjs +27 -0
- package/scripts/cli/index.mjs +79 -0
- package/scripts/cli/init.mjs +153 -0
- package/scripts/cli/release.mjs +152 -0
- package/scripts/cli/run.mjs +96 -0
- package/scripts/cli.mjs +2 -560
- package/scripts/package-smoke.mjs +4 -1
- package/scripts/preview.mjs +17 -61
- package/scripts/size-budget.mjs +5 -2
- package/scripts/vite.default.mjs +11 -0
- package/starters/default/.editorconfig +12 -0
- package/starters/default/README.md +74 -0
- package/starters/default/eslint.config.mjs +256 -0
- package/starters/default/index.html +13 -0
- package/starters/default/package.json +30 -0
- package/starters/default/public/favicon.svg +4 -0
- package/starters/default/src/app.routes.ts +39 -0
- package/starters/default/src/layouts/app-shell.layout.ts +35 -0
- package/starters/default/src/layouts/auth-shell.layout.ts +17 -0
- package/starters/default/src/main.ts +16 -0
- package/starters/default/src/modules/auth/_contracts/auth-api.types.ts +17 -0
- package/starters/default/src/modules/auth/auth.connector.ts +45 -0
- package/starters/default/src/modules/auth/auth.guard.ts +22 -0
- package/starters/default/src/modules/auth/auth.public.ts +9 -0
- package/starters/default/src/modules/auth/auth.routes.ts +8 -0
- package/starters/default/src/modules/auth/auth.service.ts +71 -0
- package/starters/default/src/modules/auth/auth.types.ts +15 -0
- package/starters/default/src/modules/auth/login.page.ts +62 -0
- package/starters/default/src/modules/billing/_contracts/stripe.types.ts +17 -0
- package/starters/default/src/modules/billing/api/stripe.connector.ts +71 -0
- package/starters/default/src/modules/billing/billing.public.ts +5 -0
- package/starters/default/src/modules/billing/billing.routes.ts +9 -0
- package/starters/default/src/modules/billing/billing.types.ts +15 -0
- package/starters/default/src/modules/billing/components/invoice-status-badge.component.ts +43 -0
- package/starters/default/src/modules/billing/data/invoices.resource.ts +35 -0
- package/starters/default/src/modules/billing/pages/invoice-detail.page.ts +70 -0
- package/starters/default/src/modules/billing/pages/invoices-list.page.ts +73 -0
- package/starters/default/src/modules/home/home.page.ts +34 -0
- package/starters/default/src/modules/home/not-found.page.ts +11 -0
- package/starters/default/src/shared/http/http-client.ts +86 -0
- package/starters/default/src/shared/http/http-error.ts +37 -0
- package/starters/default/src/shared/http/interceptors.ts +59 -0
- package/starters/default/src/shared/lib/format-date.ts +19 -0
- package/starters/default/src/shared/styles/content.css +70 -0
- package/starters/default/src/shared/styles/reset.css +32 -0
- package/starters/default/src/shared/styles/shell.css +57 -0
- package/starters/default/src/shared/styles/tokens.css +44 -0
- package/starters/default/src/shared/ui/x-button.component.ts +49 -0
- package/starters/default/src/shared/ui/x-spinner.component.ts +22 -0
- package/starters/default/src/styles.d.ts +1 -0
- package/starters/default/src/vite-env.d.ts +1 -0
- package/starters/default/tsconfig.json +24 -0
- package/starters/default/vite.config.ts +9 -0
- package/MADO_V1_PLAN.md +0 -179
- package/ROADMAP.md +0 -178
- package/dist/src/html.d.ts +0 -18
- package/dist/src/html.js +0 -17
- package/dist/src/html.js.map +0 -1
- package/dist/src/router.d.ts +0 -13
- package/dist/src/router.js +0 -13
- package/dist/src/router.js.map +0 -1
- package/scripts/bundle.mjs +0 -212
- package/scripts/llm-zero-history-smoke.mjs +0 -93
- package/scripts/new.mjs +0 -80
- package/scripts/showcase-regression.mjs +0 -392
- package/server/serve.mjs +0 -455
- package/starters/admin/README.md +0 -63
- package/starters/admin/index.html +0 -28
- package/starters/admin/mado.config.json +0 -22
- package/starters/admin/package.json +0 -24
- package/starters/admin/public/favicon.svg +0 -4
- package/starters/admin/src/components/x-button.ts +0 -82
- package/starters/admin/src/components/x-input.ts +0 -105
- package/starters/admin/src/layouts/app.ts +0 -101
- package/starters/admin/src/layouts/auth.ts +0 -41
- package/starters/admin/src/lib/api.ts +0 -184
- package/starters/admin/src/lib/auth.ts +0 -83
- package/starters/admin/src/main.ts +0 -15
- package/starters/admin/src/pages/admin/dashboard.ts +0 -48
- package/starters/admin/src/pages/admin/order-detail.ts +0 -80
- package/starters/admin/src/pages/admin/orders.ts +0 -117
- package/starters/admin/src/pages/home.ts +0 -34
- package/starters/admin/src/pages/login.ts +0 -70
- package/starters/admin/src/pages/not-found.ts +0 -12
- package/starters/admin/src/routes.ts +0 -40
- package/starters/admin/src/styles/global.ts +0 -86
- package/starters/admin/tsconfig.json +0 -15
- package/starters/crud/README.md +0 -33
- package/starters/crud/index.html +0 -28
- package/starters/crud/mado.config.json +0 -20
- package/starters/crud/package.json +0 -24
- package/starters/crud/src/components/app-shell.ts +0 -56
- package/starters/crud/src/components/ticket-detail.ts +0 -33
- package/starters/crud/src/components/ticket-form.ts +0 -69
- package/starters/crud/src/components/ticket-list.ts +0 -66
- package/starters/crud/src/lib/api.ts +0 -76
- package/starters/crud/src/main.ts +0 -9
- package/starters/crud/src/pages/home.ts +0 -34
- package/starters/crud/src/pages/not-found.ts +0 -12
- package/starters/crud/src/pages/ticket-detail.ts +0 -7
- package/starters/crud/src/pages/ticket-new.ts +0 -7
- package/starters/crud/src/pages/tickets.ts +0 -7
- package/starters/crud/src/routes.ts +0 -11
- package/starters/crud/src/styles/global.ts +0 -155
- package/starters/crud/tsconfig.json +0 -15
- package/starters/minimal/README.md +0 -21
- package/starters/minimal/index.html +0 -28
- package/starters/minimal/mado.config.json +0 -20
- package/starters/minimal/package.json +0 -24
- package/starters/minimal/src/components/app-counter.ts +0 -31
- package/starters/minimal/src/main.ts +0 -9
- package/starters/minimal/src/pages/home.ts +0 -35
- package/starters/minimal/src/pages/not-found.ts +0 -14
- package/starters/minimal/src/routes.ts +0 -8
- package/starters/minimal/src/styles/global.ts +0 -60
- package/starters/minimal/tsconfig.json +0 -15
- package/templates/page-detail.ts +0 -63
- package/templates/page-form.ts +0 -94
- package/templates/page-list.ts +0 -79
package/docs/ru/13-deployment.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Deployment
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Одна команда, один deploy artifact:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
mado release
|
|
@@ -10,15 +10,18 @@ mado release
|
|
|
10
10
|
|
|
11
11
|
```txt
|
|
12
12
|
out/
|
|
13
|
-
├── index.html
|
|
14
|
-
├── assets/
|
|
15
|
-
├──
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
├── index.html ← SPA shell или baked HTML для /
|
|
14
|
+
├── assets/ ← Vite hashed assets
|
|
15
|
+
│ ├── *.gz ← precompressed gzip
|
|
16
|
+
│ └── *.br ← precompressed brotli
|
|
17
|
+
├── <route>/index.html ← baked HTML для static hosts
|
|
18
|
+
├── sitemap.xml ← sitemap в root сайта
|
|
19
|
+
├── _redirects ← Cloudflare Pages / Netlify SPA fallback
|
|
20
|
+
└── _headers ← cache rules
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
`out/` можно деплоить на nginx, Cloudflare Pages, Netlify, S3/CloudFront или
|
|
21
|
-
GitHub Pages.
|
|
24
|
+
GitHub Pages. Деплоится только `out/`.
|
|
22
25
|
|
|
23
26
|
## Preview
|
|
24
27
|
|
|
@@ -27,8 +30,9 @@ mado release
|
|
|
27
30
|
mado preview
|
|
28
31
|
```
|
|
29
32
|
|
|
30
|
-
`mado preview` сервит `out/` как
|
|
31
|
-
|
|
33
|
+
`mado preview` сервит финальный `out/` как обычный static host: сначала реальные
|
|
34
|
+
файлы (`/<route>/index.html`, если route был baked), потом SPA fallback в
|
|
35
|
+
`index.html`. Preview проверяет ровно то, что будет загружено на хостинг.
|
|
32
36
|
|
|
33
37
|
## VPS + nginx
|
|
34
38
|
|
|
@@ -37,8 +41,8 @@ mado release
|
|
|
37
41
|
rsync -avz --delete out/ user@server:/var/www/myapp/
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
Опциональный nginx-рецепт лежит в `docs/recipes/nginx/`: assets кешируются
|
|
45
|
+
immutable, HTML идет с `no-cache`, deep links работают через SPA fallback.
|
|
42
46
|
|
|
43
47
|
## Cloudflare / Netlify
|
|
44
48
|
|
|
@@ -47,9 +51,11 @@ mado release
|
|
|
47
51
|
npx wrangler pages deploy out --project-name=myapp
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
`_redirects` и `_headers` генерируются
|
|
54
|
+
`_redirects` и `_headers` генерируются автоматически, если ты не положил свои.
|
|
55
|
+
Baked routes промотируются в реальные файлы (`out/<route>/index.html`), поэтому
|
|
56
|
+
static host отдаст их до SPA fallback.
|
|
51
57
|
|
|
52
|
-
## Cache
|
|
58
|
+
## Cache Rules
|
|
53
59
|
|
|
54
60
|
| Path | Cache-Control |
|
|
55
61
|
|---|---|
|
package/docs/ru/14-testing.md
CHANGED
|
@@ -26,7 +26,7 @@ globalThis.document = window.document;
|
|
|
26
26
|
globalThis.Node = window.Node;
|
|
27
27
|
globalThis.HTMLElement = window.HTMLElement;
|
|
28
28
|
|
|
29
|
-
const { html, render } = await import("../dist/src/html.js");
|
|
29
|
+
const { html, render } = await import("../dist/src/html/template.js");
|
|
30
30
|
|
|
31
31
|
test("renders a value", () => {
|
|
32
32
|
const root = document.createElement("div");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# Bake
|
|
1
|
+
# Bake Cookbook
|
|
2
2
|
|
|
3
3
|
`mado bake` рендерит выбранные роуты в статический HTML. Это для SEO и быстрого
|
|
4
4
|
первого ответа, не SSR с hydration.
|
|
5
5
|
|
|
6
|
-
## Минимальная
|
|
6
|
+
## Минимальная Страница
|
|
7
7
|
|
|
8
8
|
```ts
|
|
9
9
|
export default page({
|
|
@@ -23,9 +23,9 @@ export default page({
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
В baked views лучше использовать обычные массивы (`items.map(...)`). Runtime
|
|
26
|
-
директивы вроде `each()` нужны браузеру.
|
|
26
|
+
директивы вроде keyed `each()` нужны браузеру.
|
|
27
27
|
|
|
28
|
-
## Dynamic
|
|
28
|
+
## Dynamic Routes
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
31
|
export default page<{ slug: string }>({
|
|
@@ -40,16 +40,56 @@ export default page<{ slug: string }>({
|
|
|
40
40
|
|
|
41
41
|
`unsafeHTML()` используй только для доверенного или заранее очищенного HTML.
|
|
42
42
|
|
|
43
|
-
## Manifest
|
|
43
|
+
## Route Manifest
|
|
44
|
+
|
|
45
|
+
`mado bake` нужен source manifest:
|
|
44
46
|
|
|
45
47
|
```ts
|
|
46
48
|
export const manifest = {
|
|
47
49
|
"/": () => import("./pages/home.js"),
|
|
48
50
|
"/blog/:slug": () => import("./pages/blog-post.js"),
|
|
49
51
|
};
|
|
52
|
+
|
|
50
53
|
export default routes(manifest);
|
|
51
54
|
```
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
## Output
|
|
57
|
+
|
|
58
|
+
Standalone `mado bake` по умолчанию пишет baked pages прямо в `out/`.
|
|
59
|
+
`mado release` сначала запускает Vite build, затем bake заменяет route HTML
|
|
60
|
+
на месте и пишет sitemap в `out/sitemap.xml`.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
mado release
|
|
64
|
+
tree out
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Deployable folder — `out/`, не `dist/`.
|
|
68
|
+
|
|
69
|
+
`mado release --keep-bake-dir` оставляет дополнительную копию `out/baked/`
|
|
70
|
+
только для debugging/inspection.
|
|
71
|
+
|
|
72
|
+
## Client Boot
|
|
73
|
+
|
|
74
|
+
Baked HTML помечает `#app` атрибутом `data-mado-baked`. Это не hydration:
|
|
75
|
+
клиентский `render()` заменяет baked DOM живыми bindings при старте приложения.
|
|
76
|
+
Так первый ответ содержит SEO/first-paint HTML, а SPA после загрузки работает
|
|
77
|
+
как обычно.
|
|
78
|
+
|
|
79
|
+
## Unsupported Values
|
|
80
|
+
|
|
81
|
+
Bake намеренно падает громко вместо записи `[object Object]`. Если baked view
|
|
82
|
+
ругается на unsupported directive:
|
|
83
|
+
|
|
84
|
+
- замени `each()` на `items.map(...)` в baked markup;
|
|
85
|
+
- интерактивные виджеты оставь в client-only routes;
|
|
86
|
+
- убедись, что все значения сериализуются в статический HTML.
|
|
87
|
+
|
|
88
|
+
## Canonical Links
|
|
89
|
+
|
|
90
|
+
Передай `--base-url`, чтобы canonical links и sitemap указывали на production.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
mado bake --base-url https://example.com
|
|
94
|
+
mado release --base-url https://example.com
|
|
95
|
+
```
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
import { component, html, resource, routes, signal } from "@madojs/mado";
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Публичные subpaths — side-effect модуль devtools и Vite integration:
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
15
|
import "@madojs/mado/devtools.js";
|
|
16
|
+
import { mado } from "@madojs/mado/vite";
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
Все остальное под `dist/src/` — деталь реализации, даже если файл виден в
|
|
@@ -27,7 +28,7 @@ import "@madojs/mado/devtools.js";
|
|
|
27
28
|
- Templates и directives: `html`, `render`, `each`, `list`, `unsafeHTML`,
|
|
28
29
|
`ref`, `classMap`, `styleMap`.
|
|
29
30
|
- Components и CSS: `component`, `css`, `cssVars`.
|
|
30
|
-
- Routing и pages: `routes`, `router`, `page`, `layout`,
|
|
31
|
+
- Routing и pages: `routes`, `router`, `page`, `layout`,
|
|
31
32
|
`navigate`, `queryParam`, `prefetchPath`.
|
|
32
33
|
- Data: `resource`, `mutation`, `invalidate`, `jsonFetcher`, `HttpError`.
|
|
33
34
|
- Forms: `useForm`.
|
|
@@ -41,7 +42,8 @@ import "@madojs/mado/devtools.js";
|
|
|
41
42
|
|
|
42
43
|
Это не публичный API:
|
|
43
44
|
|
|
44
|
-
- Package subpaths кроме `@madojs/mado
|
|
45
|
+
- Package subpaths кроме `@madojs/mado`, `@madojs/mado/devtools.js` и
|
|
46
|
+
`@madojs/mado/vite`.
|
|
45
47
|
- Internals парсера/биндингов: `html/parser.js`, `html/bindings.js`,
|
|
46
48
|
`ChildState`, `EachEntry`.
|
|
47
49
|
- Internals роутера: `router/match.js`, `router/navigation.js`,
|
|
@@ -25,7 +25,7 @@ byte, starter copy или diagnostic string заморожены навсегд
|
|
|
25
25
|
deferred teardown для same-tick moves, cleanup через `ctx.onDispose`.
|
|
26
26
|
- Router/page/resource/form contracts, описанные в English docs.
|
|
27
27
|
- Имена CLI commands и широкий смысл команд (`build`, `dev`, `release`,
|
|
28
|
-
`bake`, `
|
|
28
|
+
`bake`, `preview`, `init`, `new`).
|
|
29
29
|
|
|
30
30
|
Ломать это можно только в major version.
|
|
31
31
|
|
|
@@ -2,55 +2,81 @@
|
|
|
2
2
|
|
|
3
3
|
> Один зрозумілий шлях. Жорсткі контракти. Мінімум магії.
|
|
4
4
|
|
|
5
|
-
Mado —
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```text
|
|
5
|
+
Mado — framework для команд, що будують admin panels, internal tools і
|
|
6
|
+
business SPA. Такі apps мають бути простими у розробці та нудними в підтримці,
|
|
7
|
+
тому Mado обирає чіткі conventions замість п'яти рівноправних стилів.
|
|
8
|
+
|
|
9
|
+
## Principles
|
|
10
|
+
|
|
11
|
+
1. **One way.** If code feels unusual, first check whether a canonical helper/API
|
|
12
|
+
already exists.
|
|
13
|
+
2. **Explicit over magic.** No file-system scanners, implicit globals or hidden
|
|
14
|
+
side effects.
|
|
15
|
+
3. **Platform first.** Web Components, History API, `<form>`, `fetch` and Shadow
|
|
16
|
+
DOM stay visible.
|
|
17
|
+
4. **Strict types.** `tsc --strict --noUncheckedIndexedAccess` always.
|
|
18
|
+
5. **No runtime dependencies.** Dev/build tooling is fine; Mado runtime stays
|
|
19
|
+
native.
|
|
20
|
+
|
|
21
|
+
## Project Structure
|
|
22
|
+
|
|
23
|
+
```txt
|
|
26
24
|
src/
|
|
27
|
-
├──
|
|
28
|
-
├──
|
|
29
|
-
├──
|
|
30
|
-
├──
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
├── main.ts ← boot: global CSS/providers + render router
|
|
26
|
+
├── app.routes.ts ← readable app map, exports `manifest` + default routes()
|
|
27
|
+
├── layouts/ ← app-zone wrappers (`page({ view: ({ child }) => ... })`)
|
|
28
|
+
├── shared/ ← UI bricks, http client, pure lib, global CSS
|
|
29
|
+
└── modules/ ← bounded contexts
|
|
30
|
+
└── billing/
|
|
31
|
+
├── billing.routes.ts
|
|
32
|
+
├── billing.public.ts
|
|
33
|
+
├── billing.types.ts
|
|
34
|
+
├── pages/
|
|
35
|
+
├── data/
|
|
36
|
+
├── api/
|
|
37
|
+
└── _contracts/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The default starter is the canonical version of this shape.
|
|
41
|
+
|
|
42
|
+
## One Component = One File
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { component, css, html } from "@madojs/mado";
|
|
46
|
+
|
|
47
|
+
component("x-user-card", () => () => html`<div class="card"><slot></slot></div>`, {
|
|
48
|
+
styles: css`
|
|
49
|
+
.card { padding: 1rem; }
|
|
50
|
+
`,
|
|
51
|
+
});
|
|
34
52
|
```
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
зміни виконуються через `mutation()`, списки рендеряться через `each()`.
|
|
54
|
+
Importing the component file registers the element. Import it where the tag is
|
|
55
|
+
used.
|
|
39
56
|
|
|
40
|
-
##
|
|
57
|
+
## One Way To Describe A Page
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { html, page, resource, jsonFetcher } from "@madojs/mado";
|
|
61
|
+
|
|
62
|
+
export default page({
|
|
63
|
+
title: ({ id }) => `User #${id}`,
|
|
64
|
+
view: ({ params }) => {
|
|
65
|
+
const user = resource(() => `/api/users/${params.id}`, jsonFetcher());
|
|
66
|
+
return html`...`;
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
```
|
|
41
70
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
префікс домену: `app-*`, `crm-*`, `ticket-*`, `admin-*`.
|
|
71
|
+
Page-local signals, resources and forms live inside `view()`. Module-wide state
|
|
72
|
+
lives in `*.service.ts`.
|
|
45
73
|
|
|
46
|
-
##
|
|
74
|
+
## What We Do Not Do
|
|
47
75
|
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
стану; використовуємо `each()`.
|
|
54
|
-
- Не додаємо runtime-залежності без дуже вагомої причини.
|
|
76
|
+
- No JSX/Vue/Svelte syntax.
|
|
77
|
+
- No custom elements without a hyphen.
|
|
78
|
+
- No signal `.value`; a signal is a function.
|
|
79
|
+
- No direct `innerHTML`.
|
|
80
|
+
- No runtime packages without discussion.
|
|
55
81
|
|
|
56
|
-
|
|
82
|
+
When in doubt, document one clear recipe instead of adding a new core primitive.
|
package/docs/uk/01-routing.md
CHANGED
|
@@ -1,76 +1,70 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Routing
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
> One app map. No folder scanners. No magic path syntax.
|
|
4
|
+
|
|
5
|
+
Mado uses an explicit route manifest. Route composition should be readable in
|
|
6
|
+
one place: `src/app.routes.ts`.
|
|
5
7
|
|
|
6
8
|
```ts
|
|
7
|
-
import { routes } from "@madojs/mado";
|
|
9
|
+
import { layout, routes } from "@madojs/mado";
|
|
10
|
+
import { requireAuth } from "./modules/auth/auth.public";
|
|
11
|
+
import { authRoutes } from "./modules/auth/auth.routes";
|
|
12
|
+
import { billingRoutes } from "./modules/billing/billing.routes";
|
|
8
13
|
|
|
9
14
|
export const manifest = {
|
|
10
|
-
"/": () => import("./
|
|
11
|
-
"/
|
|
12
|
-
|
|
15
|
+
"/": () => import("./modules/home/home.page.js"),
|
|
16
|
+
"/login": layout({
|
|
17
|
+
layout: () => import("./layouts/auth-shell.layout.js"),
|
|
18
|
+
routes: authRoutes,
|
|
19
|
+
}),
|
|
20
|
+
"/billing": layout({
|
|
21
|
+
layout: () => import("./layouts/app-shell.layout.js"),
|
|
22
|
+
guard: requireAuth,
|
|
23
|
+
routes: billingRoutes,
|
|
24
|
+
}),
|
|
25
|
+
"*": () => import("./modules/home/not-found.page.js"),
|
|
13
26
|
};
|
|
14
27
|
|
|
15
28
|
export default routes(manifest);
|
|
16
29
|
```
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
```ts
|
|
21
|
-
import { page, html } from "@madojs/mado";
|
|
22
|
-
|
|
23
|
-
export default page<{ id: string }>({
|
|
24
|
-
title: ({ id }) => `User ${id}`,
|
|
25
|
-
view: ({ params }) => html`<x-user data-id=${params.id}></x-user>`,
|
|
26
|
-
});
|
|
27
|
-
```
|
|
31
|
+
Export `manifest` so `mado bake` can read it.
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
Маршрут може бути lazy import або готовим `page({...})`.
|
|
33
|
+
## Module Routes
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
Modules export plain route maps. They do not call `layout()`.
|
|
33
36
|
|
|
34
37
|
```ts
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"/": () => import("./pages/home.js"),
|
|
39
|
-
"/app": nested({
|
|
40
|
-
layout: () => import("./layouts/app-layout.js"),
|
|
41
|
-
routes: {
|
|
42
|
-
"/dashboard": () => import("./pages/dashboard.js"),
|
|
43
|
-
"/settings": () => import("./pages/settings.js"),
|
|
44
|
-
},
|
|
45
|
-
}),
|
|
38
|
+
export const billingRoutes = {
|
|
39
|
+
"/invoices": () => import("./pages/invoices-list.page.js"),
|
|
40
|
+
"/invoices/:id": () => import("./pages/invoice-detail.page.js"),
|
|
46
41
|
};
|
|
47
|
-
|
|
48
|
-
export default routes(manifest);
|
|
49
42
|
```
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
notifications.
|
|
44
|
+
The prefix is applied by `src/app.routes.ts`.
|
|
53
45
|
|
|
54
|
-
##
|
|
46
|
+
## Page
|
|
55
47
|
|
|
56
|
-
|
|
48
|
+
```ts
|
|
49
|
+
import { html, page } from "@madojs/mado";
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
export default page<{ id: string }>({
|
|
52
|
+
title: ({ id }) => `User ${id}`,
|
|
53
|
+
view: ({ params }) => html`<h1>${params.id}</h1>`,
|
|
54
|
+
});
|
|
60
55
|
```
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
## Navigation
|
|
63
58
|
|
|
64
59
|
```ts
|
|
65
|
-
import
|
|
60
|
+
import appRoutes from "./app.routes.js";
|
|
66
61
|
|
|
67
|
-
navigate("/
|
|
62
|
+
appRoutes.navigate("/billing/invoices");
|
|
63
|
+
appRoutes.navigate("/billing/invoices?page=2");
|
|
64
|
+
appRoutes.navigate("/login", { replace: true });
|
|
68
65
|
```
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
навігації та `dispose()` для тестів/dev overlay.
|
|
72
|
-
|
|
73
|
-
## Query params
|
|
67
|
+
## Query Params
|
|
74
68
|
|
|
75
69
|
```ts
|
|
76
70
|
import { queryParam } from "@madojs/mado";
|
|
@@ -79,4 +73,4 @@ const search = queryParam("q", "");
|
|
|
79
73
|
search.set("mado");
|
|
80
74
|
```
|
|
81
75
|
|
|
82
|
-
`queryParam()`
|
|
76
|
+
`queryParam()` returns a signal-like API and syncs state with the URL.
|
|
@@ -1,46 +1,73 @@
|
|
|
1
1
|
# Структура проєкту
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
├──
|
|
9
|
-
├──
|
|
10
|
-
├──
|
|
11
|
-
├──
|
|
12
|
-
├──
|
|
13
|
-
└──
|
|
3
|
+
Кожен Mado-застосунок використовує одну канонічну форму. Це потрібно, щоб люди
|
|
4
|
+
й AI-асистенти однаково розуміли, де живе код.
|
|
5
|
+
|
|
6
|
+
```txt
|
|
7
|
+
my-app/
|
|
8
|
+
├── package.json # runtime dep: @madojs/mado
|
|
9
|
+
├── tsconfig.json # strict TS, ES2022, Bundler resolution
|
|
10
|
+
├── vite.config.ts # mado() from @madojs/mado/vite
|
|
11
|
+
├── index.html # Vite entry + SPA shell
|
|
12
|
+
├── public/ # static assets: favicon, images, robots.txt
|
|
13
|
+
└── src/
|
|
14
|
+
├── main.ts # imports CSS and mounts router into #app
|
|
15
|
+
├── app.routes.ts # app map: manifest + default routes(...)
|
|
16
|
+
├── layouts/ # app-zone layouts
|
|
17
|
+
├── shared/ # ui, http, lib, styles
|
|
18
|
+
└── modules/ # bounded contexts
|
|
19
|
+
└── billing/
|
|
20
|
+
├── billing.routes.ts
|
|
21
|
+
├── billing.public.ts
|
|
22
|
+
├── billing.types.ts
|
|
23
|
+
├── pages/
|
|
24
|
+
├── data/
|
|
25
|
+
├── api/
|
|
26
|
+
└── _contracts/
|
|
14
27
|
```
|
|
15
28
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
## Artifact States
|
|
30
|
+
|
|
31
|
+
| Folder | Що це | Хто пише | Deploy? |
|
|
32
|
+
| --- | --- | --- | --- |
|
|
33
|
+
| `src/` | TypeScript sources | ви | no |
|
|
34
|
+
| `public/` | static assets copied as-is | ви | via `out/` |
|
|
35
|
+
| `out/` | deploy artifact: SPA shell + assets + baked HTML | `mado release` | yes |
|
|
36
|
+
|
|
37
|
+
`mado release` = `typecheck` + Vite build (`out/index.html`, `out/assets/`,
|
|
38
|
+
`public/*`) + `bake` directly into route paths + `sitemap.xml` + precompression.
|
|
39
|
+
|
|
40
|
+
## Where To Put Files
|
|
41
|
+
|
|
42
|
+
| What | Where |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| Page for a new URL | `src/modules/<module>/pages/<name>.page.ts` + module routes |
|
|
45
|
+
| Module route map | `src/modules/<module>/<module>.routes.ts` |
|
|
46
|
+
| App shell/layout | `src/layouts/<zone>.layout.ts` |
|
|
47
|
+
| Shared UI widget | `src/shared/ui/<x-name>.component.ts` |
|
|
48
|
+
| Module-only UI widget | `src/modules/<module>/components/<name>.component.ts` |
|
|
49
|
+
| API connector | `src/modules/<module>/api/<provider>.connector.ts` |
|
|
50
|
+
| Data resource/mutation | `src/modules/<module>/data/<name>.resource.ts` |
|
|
51
|
+
| Auth/session | `src/modules/auth/` |
|
|
52
|
+
| Public module surface | `src/modules/<module>/<module>.public.ts` |
|
|
53
|
+
| Pure function without UI | `src/shared/lib/<name>.ts` |
|
|
54
|
+
| Static image / favicon | `public/<file>` |
|
|
55
|
+
| App-zone shell CSS | `src/shared/styles/shell.css` |
|
|
56
|
+
| Page-level CSS | `src/shared/styles/content.css` |
|
|
57
|
+
|
|
58
|
+
## Vite Config
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { defineConfig } from "vite";
|
|
62
|
+
import { mado } from "@madojs/mado/vite";
|
|
63
|
+
|
|
64
|
+
export default defineConfig({
|
|
65
|
+
plugins: [mado()],
|
|
66
|
+
css: {
|
|
67
|
+
transformer: "lightningcss",
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
```
|
|
44
71
|
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
Starter uses Vite's Lightning CSS transformer. Mado does not own prefixing, CSS
|
|
73
|
+
lowering or minification.
|
|
@@ -42,8 +42,7 @@ export default page<{ slug: string }, Product>({
|
|
|
42
42
|
## Edge prerender
|
|
43
43
|
|
|
44
44
|
Для великих наборів сторінок можна робити той самий підхід на edge: Cloudflare
|
|
45
|
-
Worker генерує HTML на cache miss, кладе в KV і віддає з TTL.
|
|
46
|
-
`examples/cloudflare`.
|
|
45
|
+
Worker генерує HTML на cache miss, кладе в KV і віддає з TTL.
|
|
47
46
|
|
|
48
47
|
Це не hydration. Клієнтський Mado-застосунок все одно стартує нормально і
|
|
49
48
|
перерендерює сторінку після завантаження.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|---|---|
|
|
8
8
|
| router | `routes()` |
|
|
9
9
|
| handler | `page().view` |
|
|
10
|
-
| middleware/layout | `
|
|
10
|
+
| middleware/layout | `layout()` route group |
|
|
11
11
|
| cache get-or-set | `resource()` |
|
|
12
12
|
| POST/PUT/DELETE | `mutation()` |
|
|
13
13
|
| cache invalidation | `invalidates` / `invalidate()` |
|
|
@@ -44,8 +44,8 @@ Mado використовує schema-based validation, близьку до HTML
|
|
|
44
44
|
|
|
45
45
|
## Auth
|
|
46
46
|
|
|
47
|
-
Auth зазвичай живе в `
|
|
48
|
-
робити через
|
|
47
|
+
Auth зазвичай живе в `modules/auth` як signal/context. Protected area зручно
|
|
48
|
+
робити через `layout()` group, який перевіряє session і показує dashboard або
|
|
49
49
|
redirect/login.
|
|
50
50
|
|
|
51
51
|
## Правило
|