@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/01-routing.md
CHANGED
|
@@ -1,194 +1,119 @@
|
|
|
1
1
|
# Routing
|
|
2
2
|
|
|
3
|
-
> Один
|
|
3
|
+
> Один app map. Никаких folder scanners. Никаких специальных path symbols.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Mado не выводит routes из файлов. Composition должна читаться в одном месте.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## App Manifest
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- Спецсимволы в путях: `[id]`, `(group)`, `_layout`, `+page.svelte`, `...slug`.
|
|
11
|
-
- Server-route vs client-route путаются.
|
|
12
|
-
- Тестировать роутинг — мука: нужен эмулятор сборщика.
|
|
13
|
-
|
|
14
|
-
Mado считает это **слишком магией**. Мы делаем иначе.
|
|
15
|
-
|
|
16
|
-
## Манифест
|
|
17
|
-
|
|
18
|
-
Один файл — `src/routes.ts`. В нём один объект. Читается сверху вниз.
|
|
9
|
+
Используйте `src/app.routes.ts` как карту приложения:
|
|
19
10
|
|
|
20
11
|
```ts
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
import { layout, routes } from "@madojs/mado";
|
|
13
|
+
import { requireAuth } from "./modules/auth/auth.public";
|
|
14
|
+
import { authRoutes } from "./modules/auth/auth.routes";
|
|
15
|
+
import { billingRoutes } from "./modules/billing/billing.routes";
|
|
16
|
+
|
|
17
|
+
export const manifest = {
|
|
18
|
+
"/": () => import("./modules/home/home.page.js"),
|
|
19
|
+
"/login": layout({
|
|
20
|
+
layout: () => import("./layouts/auth-shell.layout.js"),
|
|
21
|
+
routes: authRoutes,
|
|
22
|
+
}),
|
|
23
|
+
"/billing": layout({
|
|
24
|
+
layout: () => import("./layouts/app-shell.layout.js"),
|
|
25
|
+
guard: requireAuth,
|
|
26
|
+
routes: billingRoutes,
|
|
27
|
+
}),
|
|
28
|
+
"*": () => import("./modules/home/not-found.page.js"),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default routes(manifest);
|
|
31
32
|
```
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
Открываешь `app.routes.ts` и видишь все зоны приложения: public pages, auth,
|
|
35
|
+
protected app zones, guards и shells.
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
`manifest` экспортируется отдельно, чтобы `mado bake` мог его прочитать.
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
## Module Routes
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
Modules экспортируют plain route maps. Они не вызывают `layout()` и не решают,
|
|
42
|
+
какой shell их оборачивает.
|
|
40
43
|
|
|
41
44
|
```ts
|
|
42
|
-
|
|
45
|
+
export const billingRoutes = {
|
|
46
|
+
"/invoices": () => import("./pages/invoices-list.page.js"),
|
|
47
|
+
"/invoices/:id": () => import("./pages/invoice-detail.page.js"),
|
|
48
|
+
};
|
|
43
49
|
```
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- Между навигациями результат кэшируется.
|
|
51
|
+
Prefix применяет `src/app.routes.ts`, когда module монтируется под
|
|
52
|
+
`"/billing"`.
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
## Layout Group
|
|
50
55
|
|
|
51
56
|
```ts
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
"/admin": layout({
|
|
58
|
+
layout: () => import("./layouts/app-shell.layout.js"),
|
|
59
|
+
guard: requireAuth,
|
|
60
|
+
routes: adminRoutes,
|
|
61
|
+
}),
|
|
55
62
|
```
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
### 3. Nested с layout
|
|
64
|
+
Layout — обычный `page({...})` file:
|
|
60
65
|
|
|
61
66
|
```ts
|
|
62
|
-
import {
|
|
63
|
-
|
|
64
|
-
export default routes({
|
|
65
|
-
'/': () => import('./pages/home.js'),
|
|
66
|
-
|
|
67
|
-
'/admin/*': nested({
|
|
68
|
-
layout: () => import('./layouts/admin.js'),
|
|
69
|
-
routes: {
|
|
70
|
-
'': () => import('./pages/admin/dashboard.js'),
|
|
71
|
-
'users': () => import('./pages/admin/users.js'),
|
|
72
|
-
'logs': () => import('./pages/admin/logs.js'),
|
|
73
|
-
},
|
|
74
|
-
}),
|
|
75
|
-
});
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Layout — это **обычный** `page({...})`, который рендерит `ctx.child` куда хочет:
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
// src/layouts/admin.ts
|
|
82
|
-
import { page, html, css, component } from '@madojs/mado';
|
|
67
|
+
import { html, page } from "@madojs/mado";
|
|
83
68
|
|
|
84
69
|
export default page({
|
|
85
70
|
view: ({ child }) => html`
|
|
86
|
-
<div class="
|
|
87
|
-
<
|
|
88
|
-
<main>${child}</main>
|
|
71
|
+
<div class="layout layout--app">
|
|
72
|
+
<main class="app-main">${child}</main>
|
|
89
73
|
</div>
|
|
90
74
|
`,
|
|
91
75
|
});
|
|
92
76
|
```
|
|
93
77
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
import { page, html, resource, jsonFetcher } from '@madojs/mado';
|
|
98
|
-
|
|
99
|
-
export default page({
|
|
100
|
-
title: ({ id }) => `User #${id}`, // string | (params) => string
|
|
101
|
-
load: ({ id }) => resource(...), // опц., возвращает Resource или данные
|
|
102
|
-
view: ({ params, data, path, child }) => html`...`, // ОБЯЗАТЕЛЬНО
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Три слота, всё. Если ты экспортируешь не `page({...})`, а просто функцию — `routes()` кинет понятную ошибку:
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
[Mado] Lazy-роут не вернул page({...}) как default-экспорт.
|
|
110
|
-
```
|
|
78
|
+
Layout view держим stateless. Page-specific signals, resources и forms живут в
|
|
79
|
+
pages/components/resources, не в layout locals.
|
|
111
80
|
|
|
112
|
-
##
|
|
81
|
+
## Page Contract
|
|
113
82
|
|
|
114
83
|
```ts
|
|
115
|
-
|
|
116
|
-
```
|
|
84
|
+
import { html, page } from "@madojs/mado";
|
|
117
85
|
|
|
118
|
-
```ts
|
|
119
86
|
export default page<{ id: string }>({
|
|
120
87
|
title: ({ id }) => `User ${id}`,
|
|
121
|
-
view:
|
|
88
|
+
view: ({ params }) => html`<h1>${params.id}</h1>`,
|
|
122
89
|
});
|
|
123
90
|
```
|
|
124
91
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
## Глобальные опции
|
|
128
|
-
|
|
129
|
-
```ts
|
|
130
|
-
export default routes(
|
|
131
|
-
{ '/': home, '/about': about, '*': nf },
|
|
132
|
-
{
|
|
133
|
-
titleSuffix: ' · MyApp', // → "Главная · MyApp"
|
|
134
|
-
loading: () => html`<x-spinner/>`, // пока модуль грузится
|
|
135
|
-
error: (err) => html`<x-fatal-error .err=${err}/>`,
|
|
136
|
-
},
|
|
137
|
-
);
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Программная навигация
|
|
92
|
+
## Navigation
|
|
141
93
|
|
|
142
94
|
```ts
|
|
143
|
-
import
|
|
95
|
+
import appRoutes from "./app.routes.js";
|
|
144
96
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
97
|
+
appRoutes.navigate("/billing/invoices");
|
|
98
|
+
appRoutes.navigate("/billing/invoices?page=2");
|
|
99
|
+
appRoutes.navigate("/login", { replace: true });
|
|
148
100
|
```
|
|
149
101
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
## Query-параметры
|
|
102
|
+
## Query Parameters
|
|
153
103
|
|
|
154
104
|
```ts
|
|
155
|
-
import { queryParam } from
|
|
156
|
-
|
|
157
|
-
const page = queryParam('page', '1');
|
|
158
|
-
page(); // '1'
|
|
159
|
-
page.set('2'); // history.replaceState + перерисовка
|
|
160
|
-
page.set(null); // удалить параметр
|
|
161
|
-
page.set('3', { push: true }); // history.pushState
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
`queryParam` — обычный сигнал. Использовать можно где угодно: в страницах, компонентах, computed.
|
|
165
|
-
|
|
166
|
-
## Что осознанно отсутствует
|
|
105
|
+
import { queryParam } from "@madojs/mado";
|
|
167
106
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
## FAQ
|
|
174
|
-
|
|
175
|
-
**А если у меня 100 роутов? Не разрастётся ли файл?**
|
|
176
|
-
Разрастётся до ~150 строк. Это всё ещё **один источник правды** против сотни файлов в `pages/` с магическими именами. На практике даже у больших проектов (1000+ страниц) можно бить на feature-манифесты:
|
|
177
|
-
|
|
178
|
-
```ts
|
|
179
|
-
import { routes } from '@madojs/mado';
|
|
180
|
-
import adminRoutes from './features/admin/routes.js';
|
|
181
|
-
import billingRoutes from './features/billing/routes.js';
|
|
182
|
-
|
|
183
|
-
export default routes({
|
|
184
|
-
...adminRoutes,
|
|
185
|
-
...billingRoutes,
|
|
186
|
-
'*': () => import('./pages/not-found.js'),
|
|
187
|
-
});
|
|
107
|
+
const page = queryParam("page", "1");
|
|
108
|
+
page();
|
|
109
|
+
page.set("2");
|
|
110
|
+
page.set(null);
|
|
111
|
+
page.set("3", { push: true });
|
|
188
112
|
```
|
|
189
113
|
|
|
190
|
-
|
|
191
|
-
Импортируешь `routes.ts` — это просто объект. Подставляешь свой mock-router. Никакой эмуляции сборщика не нужно.
|
|
114
|
+
## Чего нет намеренно
|
|
192
115
|
|
|
193
|
-
|
|
194
|
-
|
|
116
|
+
- Auto-scan of page folders.
|
|
117
|
+
- Filesystem syntax вроде `[id]`, `(group)`, `_layout`.
|
|
118
|
+
- Server routes в client manifest.
|
|
119
|
+
- Hidden layout discovery.
|
|
@@ -1,57 +1,84 @@
|
|
|
1
|
-
# Project
|
|
1
|
+
# Project Layout
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Каждое Mado-приложение использует одну каноничную форму. Это не примерная
|
|
4
|
+
рекомендация, а соглашение, чтобы люди и AI-ассистенты одинаково понимали,
|
|
5
|
+
куда класть код.
|
|
4
6
|
|
|
5
|
-
```
|
|
7
|
+
```txt
|
|
6
8
|
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, манифесты)
|
|
9
|
+
├── package.json # runtime dep: @madojs/mado
|
|
10
|
+
├── tsconfig.json # strict TS, ES2022, Bundler resolution
|
|
11
|
+
├── vite.config.ts # mado() from @madojs/mado/vite
|
|
12
|
+
├── index.html # Vite entry + SPA shell
|
|
13
|
+
├── public/ # статика: favicon, images, robots.txt
|
|
18
14
|
└── src/
|
|
19
|
-
├── main.ts #
|
|
20
|
-
├── routes.ts
|
|
21
|
-
├──
|
|
22
|
-
├──
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
├── main.ts # импорт CSS и mount router в #app
|
|
16
|
+
├── app.routes.ts # app map: manifest + default routes(...)
|
|
17
|
+
├── layouts/ # layouts app-зон, не доменные модули
|
|
18
|
+
├── shared/ # ui, http, lib, styles
|
|
19
|
+
└── modules/ # bounded contexts
|
|
20
|
+
└── billing/
|
|
21
|
+
├── billing.routes.ts
|
|
22
|
+
├── billing.public.ts
|
|
23
|
+
├── billing.types.ts
|
|
24
|
+
├── pages/
|
|
25
|
+
├── data/
|
|
26
|
+
├── api/
|
|
27
|
+
└── _contracts/
|
|
29
28
|
```
|
|
30
29
|
|
|
30
|
+
## Artifact States
|
|
31
|
+
|
|
32
|
+
| Folder | Что это | Кто пишет | Deploy? |
|
|
33
|
+
| --- | --- | --- | --- |
|
|
34
|
+
| `src/` | исходники TypeScript | ты | no |
|
|
35
|
+
| `public/` | статика, копируется как есть | ты | через `out/` |
|
|
36
|
+
| `out/` | deploy artifact: SPA shell + assets + baked HTML | `mado release` | yes |
|
|
37
|
+
|
|
38
|
+
`mado release` = `typecheck` + Vite build (`out/index.html`, `out/assets/`,
|
|
39
|
+
`public/*`) + `bake` прямо в route paths + `sitemap.xml` + precompression.
|
|
40
|
+
|
|
41
|
+
`index.html` лежит в корне, потому что для Vite это entry template. В
|
|
42
|
+
`public/` кладите только файлы, которые нужно скопировать как есть.
|
|
43
|
+
|
|
31
44
|
## Куда положить новый файл?
|
|
32
45
|
|
|
33
46
|
| Что | Куда |
|
|
34
|
-
|
|
35
|
-
| Страница на новый URL | `src/pages
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| Страница на новый URL | `src/modules/<module>/pages/<name>.page.ts` + module routes |
|
|
49
|
+
| Module route map | `src/modules/<module>/<module>.routes.ts` |
|
|
50
|
+
| App shell/layout | `src/layouts/<zone>.layout.ts` |
|
|
51
|
+
| Shared UI widget | `src/shared/ui/<x-name>.component.ts` |
|
|
52
|
+
| Module-only UI widget | `src/modules/<module>/components/<name>.component.ts` |
|
|
53
|
+
| API connector | `src/modules/<module>/api/<provider>.connector.ts` |
|
|
54
|
+
| Data resource/mutation | `src/modules/<module>/data/<name>.resource.ts` |
|
|
55
|
+
| Auth/session | `src/modules/auth/` |
|
|
56
|
+
| Public module surface | `src/modules/<module>/<module>.public.ts` |
|
|
57
|
+
| Pure function без UI | `src/shared/lib/<name>.ts` |
|
|
58
|
+
| Static image / favicon | `public/<file>` |
|
|
59
|
+
| App-zone shell CSS | `src/shared/styles/shell.css` |
|
|
60
|
+
| Page-level CSS | `src/shared/styles/content.css` |
|
|
61
|
+
|
|
62
|
+
## Vite Config
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { defineConfig } from "vite";
|
|
66
|
+
import { mado } from "@madojs/mado/vite";
|
|
67
|
+
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
plugins: [mado()],
|
|
70
|
+
css: {
|
|
71
|
+
transformer: "lightningcss",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Starter включает Vite Lightning CSS transformer. Mado не владеет prefixing,
|
|
77
|
+
CSS lowering или minification.
|
|
78
|
+
|
|
79
|
+
## Что НЕ кладём в `src/`
|
|
80
|
+
|
|
81
|
+
- Лишние build-tool configs — настройка живет в `vite.config.ts`.
|
|
82
|
+
- `.env` files — читайте env в `src/shared/lib/config.ts` и импортируйте этот
|
|
83
|
+
модуль.
|
|
84
|
+
- Tests рядом с кодом — держите их в `test/`.
|
|
@@ -100,7 +100,7 @@ export default routes(manifest, { titleSuffix: " · MyShop" });
|
|
|
100
100
|
## Запуск
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
|
-
npm install -D linkedom
|
|
103
|
+
npm install -D linkedom vite
|
|
104
104
|
npm run build
|
|
105
105
|
npm run bake
|
|
106
106
|
```
|
|
@@ -144,7 +144,7 @@ out/
|
|
|
144
144
|
{"slug":"mado-mug","name":"Mado-кружка","price":12,"..."}
|
|
145
145
|
</script>
|
|
146
146
|
|
|
147
|
-
<script type="module" src="/
|
|
147
|
+
<script type="module" src="/assets/index-HASH.js"></script>
|
|
148
148
|
</body>
|
|
149
149
|
```
|
|
150
150
|
|
package/docs/ru/05-why-mado.md
CHANGED
|
@@ -31,11 +31,11 @@ Mado — не «убийца» React/Vue/Svelte. Это узкоспециали
|
|
|
31
31
|
| Размер | ~6 КБ | ~16 КБ |
|
|
32
32
|
| Возраст / поддержка | ~10 лет, Google | 6 месяцев, один автор |
|
|
33
33
|
| Реактивность | декораторы `@property` + ручной `requestUpdate` | сигналы (`signal`/`computed`/`effect`) из коробки |
|
|
34
|
-
| Роутер | нет, нужно искать (`@lit-labs/router`, etc) | в комплекте: `routes()` +
|
|
34
|
+
| Роутер | нет, нужно искать (`@lit-labs/router`, etc) | в комплекте: `routes()` + layout groups + prefetch |
|
|
35
35
|
| Data fetching | нет, нужно собирать | `resource()` + `mutation()` + glob-инвалидация |
|
|
36
36
|
| Формы | нет | `useForm()` с HTML-like constraints |
|
|
37
37
|
| SEO / static | сложно (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
|
|
38
|
-
| Билд |
|
|
38
|
+
| Билд | нужны framework-specific build plugins | Vite transport + native runtime |
|
|
39
39
|
| Стиль кода | классы + декораторы | функции + tagged templates |
|
|
40
40
|
| Экосистема | реальная (Shoelace, Material Web, и т.д.) | нет |
|
|
41
41
|
| Когда выбрать | пишете дизайн-систему / Web-Components-библиотеку для встраивания | пишете приложение целиком, хотите всё в одной коробке |
|
|
@@ -55,14 +55,14 @@ Mado — не «убийца» React/Vue/Svelte. Это узкоспециали
|
|
|
55
55
|
| Реактивность | сигналы (тот же класс идей) | сигналы |
|
|
56
56
|
| Шаблоны | JSX (компилируется в реактивные expressions) | tagged template `html\`\`` |
|
|
57
57
|
| Компонентная модель | функции, виртуальные узлы Solid | Web Components |
|
|
58
|
-
| Билд | Vite + babel-plugin-solid обязательны |
|
|
58
|
+
| Билд | Vite + babel-plugin-solid обязательны | Vite для dev/build, без runtime-зависимостей |
|
|
59
59
|
| Роутер | `@solidjs/router` | в комплекте |
|
|
60
60
|
| Data | `createResource` | `resource()` |
|
|
61
61
|
| SSR | поддерживается серьёзно (SolidStart) | намеренно нет |
|
|
62
62
|
| Экосистема | растёт, ~50 пакетов | нет |
|
|
63
|
-
| Когда выбрать | нужен топовый перф + JSX + готов настраивать билд |
|
|
63
|
+
| Когда выбрать | нужен топовый перф + JSX + готов настраивать билд | нужен browser-native runtime с простым tooling |
|
|
64
64
|
|
|
65
|
-
**Честный pitch:** *«Solid технически быстрее и зрелее.
|
|
65
|
+
**Честный pitch:** *«Solid технически быстрее и зрелее. Mado проще концептуально: browser-native runtime, Web Components, tagged templates, а Vite забирает на себя скучный dev/build. Если нужны JSX и большая экосистема — берите Solid.»*
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
@@ -153,7 +153,7 @@ Mado — не «убийца» React/Vue/Svelte. Это узкоспециали
|
|
|
153
153
|
|
|
154
154
|
Не размер, не перф, не сигналы — у всего этого есть конкуренты лучше.
|
|
155
155
|
|
|
156
|
-
> **«Открой исходник и прочитай его за вечер. ~3500 строк,
|
|
156
|
+
> **«Открой исходник и прочитай его за вечер. ~3500 строк, маленькие модули. Если что-то сломалось — ты не идёшь в issue на 3000 комментариев. Ты идёшь в `src/router/` и читаешь код.»**
|
|
157
157
|
|
|
158
158
|
Это называется **ownership** — ты владеешь кодом, а не зависишь от чужого.
|
|
159
159
|
|
|
@@ -13,7 +13,7 @@ Mado устроен **как HTTP-сервер**. Серьёзно:
|
|
|
13
13
|
|---|---|
|
|
14
14
|
| HTTP-роутер (chi, axum, mux) | `routes()` — манифест путей |
|
|
15
15
|
| Handler `func(req, resp)` | `page({ view: (ctx) => html\`...\` })` |
|
|
16
|
-
| Middleware |
|
|
16
|
+
| Middleware | route group через `layout()` (оборачивает handler) |
|
|
17
17
|
| Шаблонизатор (Jinja, Handlebars) | `html\`\`` tagged template |
|
|
18
18
|
| HTTP-клиент с кешем | `resource()` — fetch + cache + invalidation |
|
|
19
19
|
| Reactive variable / atom | `signal()` — реактивный геттер |
|
|
@@ -350,17 +350,17 @@ export default page({
|
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
```ts
|
|
353
|
-
// src/routes.ts
|
|
354
|
-
import {
|
|
353
|
+
// src/app.routes.ts
|
|
354
|
+
import { layout, routes } from "@madojs/mado";
|
|
355
355
|
|
|
356
356
|
export default routes({
|
|
357
357
|
"/login": () => import("./pages/login.js"),
|
|
358
358
|
|
|
359
|
-
"/app
|
|
359
|
+
"/app": layout({
|
|
360
360
|
layout: () => import("./layouts/auth-layout.js"),
|
|
361
361
|
routes: {
|
|
362
|
-
"dashboard": () => import("./pages/dashboard.js"),
|
|
363
|
-
"users": () => import("./pages/users.js"),
|
|
362
|
+
"/dashboard": () => import("./pages/dashboard.js"),
|
|
363
|
+
"/users": () => import("./pages/users.js"),
|
|
364
364
|
},
|
|
365
365
|
}),
|
|
366
366
|
});
|
|
@@ -423,6 +423,6 @@ export const api = new ApiClient("/api");
|
|
|
423
423
|
- **[`01-routing.md`](./01-routing.md)** — детально про роутер.
|
|
424
424
|
- **[`02-project-layout.md`](./02-project-layout.md)** — структура проекта.
|
|
425
425
|
- **[`03-static-bake.md`](./03-static-bake.md)** — SEO без SSR.
|
|
426
|
-
-
|
|
426
|
+
- **Внешний workspace `madojs-examples`** — полные демо (landing + admin).
|
|
427
427
|
|
|
428
428
|
Если что-то непонятно — open issue, или просто открой исходник. Это правда читается за вечер.
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
- `AGENTS.md`
|
|
14
14
|
- `README.md`
|
|
15
15
|
- `docs/en/07-llm-pitfalls.md`
|
|
16
|
-
- `examples
|
|
17
|
-
|
|
16
|
+
- файлы из внешнего workspace `madojs-examples` только если агент сам попросит
|
|
17
|
+
паттерн более крупного приложения
|
|
18
18
|
|
|
19
19
|
Агент может искать целевые API в `src/` когда заблокирован, но не должен
|
|
20
20
|
загружать весь фреймворк в контекст.
|
|
21
21
|
|
|
22
22
|
## Задание
|
|
23
23
|
|
|
24
|
-
Построить
|
|
24
|
+
Построить маленький ticket-admin SPA для соло/бекенд-разработчика.
|
|
25
25
|
|
|
26
26
|
Требуемое поведение:
|
|
27
27
|
|
|
@@ -48,15 +48,10 @@
|
|
|
48
48
|
|
|
49
49
|
## Заметки по результатам
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
Историческая реализация tickets живет во внешнем workspace `madojs-examples`.
|
|
52
|
+
Core-репозиторий больше не поставляет этот артефакт и отдельную smoke-команду;
|
|
53
|
+
используйте этот документ как ручной сценарий оценки при обновлении LLM-guidance.
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
failure patterns, затем собирает проект и запускает `test/tickets-smoke.test.mjs`.
|
|
58
|
-
|
|
59
|
-
Основная болевая точка в документации остается lifecycle: старые примеры могут
|
|
60
|
-
создать впечатление, что создание `resource()` прямо в `page.view()` допустимо.
|
|
61
|
-
Пример tickets использует page-level wrapper-компоненты вместо этого, поэтому
|
|
62
|
-
ресурсы регистрируются внутри component setup и очищаются вместе с компонентом.
|
|
55
|
+
Основная болевая точка в документации остается lifecycle: примеры не должны
|
|
56
|
+
создавать впечатление, что long-lived `resource()` можно случайно держать на
|
|
57
|
+
module scope или в route-коде без cleanup.
|