@madojs/mado 0.12.0 → 0.13.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 +15 -8
- package/CHANGELOG.md +66 -0
- package/README.md +25 -3
- package/dist/src/component.d.ts +3 -1
- package/dist/src/component.d.ts.map +1 -0
- package/dist/src/component.js +65 -30
- package/dist/src/component.js.map +1 -1
- package/dist/src/context.d.ts +13 -32
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +73 -48
- package/dist/src/context.js.map +1 -1
- package/dist/src/css.d.ts +1 -0
- package/dist/src/css.d.ts.map +1 -0
- package/dist/src/css.js.map +1 -1
- package/dist/src/devtools-hook.d.ts +14 -0
- package/dist/src/devtools-hook.d.ts.map +1 -0
- package/dist/src/devtools-hook.js +27 -0
- package/dist/src/devtools-hook.js.map +1 -0
- package/dist/src/devtools.d.ts +24 -22
- package/dist/src/devtools.d.ts.map +1 -0
- package/dist/src/devtools.js +230 -58
- package/dist/src/devtools.js.map +1 -1
- package/dist/src/diagnostics.d.ts +12 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +68 -8
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/each.d.ts +1 -5
- package/dist/src/each.d.ts.map +1 -0
- package/dist/src/each.js +0 -8
- package/dist/src/each.js.map +1 -1
- package/dist/src/forms.d.ts +27 -96
- package/dist/src/forms.d.ts.map +1 -0
- package/dist/src/forms.js +184 -394
- package/dist/src/forms.js.map +1 -1
- package/dist/src/head.d.ts +1 -0
- package/dist/src/head.d.ts.map +1 -0
- package/dist/src/head.js +2 -1
- package/dist/src/head.js.map +1 -1
- package/dist/src/html/bindings.d.ts +1 -0
- package/dist/src/html/bindings.d.ts.map +1 -0
- package/dist/src/html/bindings.js.map +1 -1
- package/dist/src/html/parser.d.ts +3 -4
- package/dist/src/html/parser.d.ts.map +1 -0
- package/dist/src/html/parser.js +63 -14
- package/dist/src/html/parser.js.map +1 -1
- package/dist/src/html/template-types.d.ts +1 -0
- package/dist/src/html/template-types.d.ts.map +1 -0
- package/dist/src/html/template-types.js.map +1 -1
- package/dist/src/html/template.d.ts +5 -1
- package/dist/src/html/template.d.ts.map +1 -0
- package/dist/src/html/template.js +78 -3
- package/dist/src/html/template.js.map +1 -1
- package/dist/src/index.d.ts +7 -8
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -7
- package/dist/src/index.js.map +1 -1
- package/dist/src/json.d.ts +3 -0
- package/dist/src/json.d.ts.map +1 -0
- package/dist/src/json.js +14 -0
- package/dist/src/json.js.map +1 -0
- package/dist/src/lifecycle.d.ts +1 -0
- package/dist/src/lifecycle.d.ts.map +1 -0
- package/dist/src/lifecycle.js +3 -2
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/page.d.ts +1 -0
- package/dist/src/page.d.ts.map +1 -0
- package/dist/src/page.js.map +1 -1
- package/dist/src/persisted.d.ts +6 -1
- package/dist/src/persisted.d.ts.map +1 -0
- package/dist/src/persisted.js +17 -11
- package/dist/src/persisted.js.map +1 -1
- package/dist/src/resource.d.ts +2 -1
- package/dist/src/resource.d.ts.map +1 -0
- package/dist/src/resource.js +126 -49
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/base.d.ts +1 -0
- package/dist/src/router/base.d.ts.map +1 -0
- package/dist/src/router/base.js.map +1 -1
- package/dist/src/router/manifest.d.ts +1 -0
- package/dist/src/router/manifest.d.ts.map +1 -0
- package/dist/src/router/manifest.js +89 -148
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/match.d.ts +1 -0
- package/dist/src/router/match.d.ts.map +1 -0
- package/dist/src/router/match.js +19 -5
- package/dist/src/router/match.js.map +1 -1
- package/dist/src/router/navigation.d.ts +1 -0
- package/dist/src/router/navigation.d.ts.map +1 -0
- package/dist/src/router/navigation.js.map +1 -1
- package/dist/src/signal.d.ts +1 -0
- package/dist/src/signal.d.ts.map +1 -0
- package/dist/src/signal.js +46 -17
- package/dist/src/signal.js.map +1 -1
- package/dist/src/static-runtime.d.ts +1 -0
- package/dist/src/static-runtime.d.ts.map +1 -0
- package/dist/src/static-runtime.js.map +1 -1
- package/dist/src/vite/index.d.ts +1 -0
- package/dist/src/vite/index.d.ts.map +1 -0
- package/dist/src/vite/index.js +4 -3
- package/dist/src/vite/index.js.map +1 -1
- package/docs/architecture/v1-roadmap.md +19 -0
- package/docs/en/10-pages-and-components.md +9 -1
- package/docs/en/13-data.md +8 -6
- package/docs/en/14-forms.md +66 -219
- package/docs/en/15-static-snapshots.md +4 -4
- package/docs/en/16-app-architecture.md +3 -2
- package/docs/en/20-deployment.md +21 -8
- package/docs/en/21-error-handling.md +9 -6
- package/docs/en/24-devtools-and-diagnostics.md +45 -0
- package/docs/en/30-api-freeze-map.md +8 -9
- package/docs/en/32-v1-stability.md +2 -2
- package/docs/en/33-migration-0.12-0.13.md +56 -0
- package/docs/en/40-llm-guide.md +7 -9
- package/docs/en/41-for-backenders.md +13 -9
- package/docs/en/42-why-mado.md +2 -2
- package/docs/en/README.md +2 -0
- package/docs/recipes/nginx/nginx.conf +2 -2
- package/llms.txt +25 -7
- package/package.json +37 -16
- package/scripts/clean.mjs +8 -0
- package/scripts/cli/generate.mjs +11 -14
- package/scripts/cli/help.mjs +2 -0
- package/scripts/cli/index.mjs +14 -6
- package/scripts/cli/init.mjs +13 -18
- package/scripts/cli/release.mjs +22 -19
- package/scripts/cli/run.mjs +5 -3
- package/scripts/logger.mjs +117 -0
- package/scripts/output-guard.mjs +128 -0
- package/scripts/preview.mjs +11 -19
- package/scripts/static/browser.mjs +58 -8
- package/scripts/static/discover.mjs +4 -1
- package/scripts/static.mjs +21 -7
- package/starters/default/package.json +4 -4
- package/starters/default/tsconfig.node.json +13 -0
- package/starters/default/vite.config.ts +0 -3
- package/starters/modular/README.md +4 -4
- package/starters/modular/package.json +4 -4
- package/starters/modular/src/layouts/app-shell.layout.ts +1 -2
- package/starters/modular/src/modules/auth/login.page.ts +5 -12
- package/starters/modular/src/modules/billing/pages/invoice-detail.page.ts +3 -4
- package/starters/modular/src/modules/billing/pages/invoices-list.page.ts +1 -1
- package/starters/modular/src/shared/styles/reset.css +21 -1
- package/starters/modular/tsconfig.json +10 -1
- package/starters/modular/tsconfig.node.json +13 -0
- package/starters/modular/vite.config.ts +6 -5
- package/dist/src/lazy.d.ts +0 -38
- package/dist/src/lazy.js +0 -73
- package/dist/src/lazy.js.map +0 -1
- package/scripts/bake.mjs +0 -5
- package/scripts/docs-lint.mjs +0 -170
- package/scripts/package-smoke.mjs +0 -135
- package/scripts/release-notes.mjs +0 -66
- package/scripts/size-budget.mjs +0 -95
- package/starters/modular/src/shared/ui/x-button.component.ts +0 -49
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import { html, page, routeUrl } from "@madojs/mado";
|
|
13
13
|
|
|
14
14
|
import { isAuthed, logout, user } from "../modules/auth/auth.public";
|
|
15
|
-
import "../shared/ui/x-button.component";
|
|
16
15
|
|
|
17
16
|
export default page({
|
|
18
17
|
title: "Mado App",
|
|
@@ -28,7 +27,7 @@ export default page({
|
|
|
28
27
|
${() =>
|
|
29
28
|
isAuthed()
|
|
30
29
|
? html`<span class="who">${() => user()?.email ?? ""}</span>
|
|
31
|
-
<
|
|
30
|
+
<button class="button button--ghost" type="button" @click=${logout}>Sign out</button>`
|
|
32
31
|
: html`<a data-link href=${routeUrl("/login")}>Sign in</a>`}
|
|
33
32
|
</nav>
|
|
34
33
|
</header>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { html, navigate, page, signal, useForm } from "@madojs/mado";
|
|
2
2
|
|
|
3
|
-
import "../../shared/ui/x-button.component";
|
|
4
|
-
|
|
5
3
|
import { login } from "./auth.service";
|
|
6
4
|
|
|
7
5
|
// 1. LOCAL STATE
|
|
@@ -16,15 +14,12 @@ import { login } from "./auth.service";
|
|
|
16
14
|
export default page({
|
|
17
15
|
title: "Sign in",
|
|
18
16
|
view: () => {
|
|
19
|
-
const submitting = signal(false);
|
|
20
17
|
const error = signal<string | null>(null);
|
|
21
18
|
const form = useForm({
|
|
22
|
-
|
|
23
|
-
password: { required: true, minLength: 6 },
|
|
19
|
+
initial: { email: "", password: "" },
|
|
24
20
|
});
|
|
25
21
|
|
|
26
22
|
const onSubmit = form.onSubmit(async (values) => {
|
|
27
|
-
submitting.set(true);
|
|
28
23
|
error.set(null);
|
|
29
24
|
try {
|
|
30
25
|
await login({
|
|
@@ -34,8 +29,6 @@ export default page({
|
|
|
34
29
|
navigate("/");
|
|
35
30
|
} catch (err) {
|
|
36
31
|
error.set(err instanceof Error ? err.message : "Login failed");
|
|
37
|
-
} finally {
|
|
38
|
-
submitting.set(false);
|
|
39
32
|
}
|
|
40
33
|
});
|
|
41
34
|
|
|
@@ -49,12 +42,12 @@ export default page({
|
|
|
49
42
|
</label>
|
|
50
43
|
<label>
|
|
51
44
|
Password
|
|
52
|
-
<input name="password" type="password" required @input=${form.onInput} />
|
|
45
|
+
<input name="password" type="password" required minlength="6" @input=${form.onInput} />
|
|
53
46
|
</label>
|
|
54
47
|
${() => (error() ? html`<p class="error">${error()}</p>` : null)}
|
|
55
|
-
<
|
|
56
|
-
${() => (submitting() ? "Signing in…" : "Sign in")}
|
|
57
|
-
</
|
|
48
|
+
<button class="button" type="submit" ?disabled=${() => form.submitting() || !form.isValid()}>
|
|
49
|
+
${() => (form.submitting() ? "Signing in…" : "Sign in")}
|
|
50
|
+
</button>
|
|
58
51
|
</form>
|
|
59
52
|
</section>
|
|
60
53
|
`;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { html, page, signal } from "@madojs/mado";
|
|
2
2
|
|
|
3
3
|
import { formatDate, formatMoney } from "../../../shared/lib/format-date";
|
|
4
|
-
import "
|
|
5
|
-
import "../../../shared/ui/x-spinner.component";
|
|
4
|
+
import "@/shared/ui/x-spinner.component";
|
|
6
5
|
|
|
7
6
|
import { hasPermission } from "../../auth/auth.public";
|
|
8
7
|
|
|
@@ -58,9 +57,9 @@ export default page({
|
|
|
58
57
|
<dt>Issued</dt><dd>${formatDate(i.issuedAt)}</dd>
|
|
59
58
|
</dl>
|
|
60
59
|
${i.status === "pending" && hasPermission("billing.invoices.pay")
|
|
61
|
-
? html`<
|
|
60
|
+
? html`<button class="button" type="button" ?disabled=${paying} @click=${onPay}>
|
|
62
61
|
${() => (paying() ? "Paying…" : "Pay now")}
|
|
63
|
-
</
|
|
62
|
+
</button>`
|
|
64
63
|
: null}
|
|
65
64
|
`;
|
|
66
65
|
})()}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { each, html, page, routeUrl, signal, untracked } from "@madojs/mado";
|
|
2
2
|
|
|
3
3
|
import { formatDate, formatMoney } from "../../../shared/lib/format-date";
|
|
4
|
-
import "
|
|
4
|
+
import "@/shared/ui/x-spinner.component";
|
|
5
5
|
|
|
6
6
|
import "../components/invoice-status-badge.component";
|
|
7
7
|
import { useInvoices } from "../data/invoices.resource";
|
|
@@ -29,4 +29,24 @@ a:hover {
|
|
|
29
29
|
button {
|
|
30
30
|
font-family: inherit;
|
|
31
31
|
font-size: inherit;
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.button {
|
|
35
|
+
padding: var(--space-2) var(--space-4);
|
|
36
|
+
border: 1px solid transparent;
|
|
37
|
+
border-radius: var(--radius-md);
|
|
38
|
+
background: var(--color-primary);
|
|
39
|
+
color: var(--color-primary-contrast);
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.button--ghost {
|
|
44
|
+
border-color: var(--color-border);
|
|
45
|
+
background: transparent;
|
|
46
|
+
color: var(--color-text);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.button:disabled {
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
opacity: 0.55;
|
|
52
|
+
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
+
"paths": {
|
|
4
|
+
"@/*": [
|
|
5
|
+
"./src/*"
|
|
6
|
+
]
|
|
7
|
+
},
|
|
3
8
|
"target": "ES2022",
|
|
4
9
|
"module": "ES2022",
|
|
5
10
|
"moduleResolution": "Bundler",
|
|
6
|
-
"lib": [
|
|
11
|
+
"lib": [
|
|
12
|
+
"ES2022",
|
|
13
|
+
"DOM",
|
|
14
|
+
"DOM.Iterable"
|
|
15
|
+
],
|
|
7
16
|
"strict": true,
|
|
8
17
|
"noImplicitOverride": true,
|
|
9
18
|
"noUncheckedIndexedAccess": true,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"types": ["node"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noUncheckedIndexedAccess": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"noEmit": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["vite.config.ts"]
|
|
13
|
+
}
|
|
@@ -16,12 +16,12 @@ function devApiMock(): Plugin {
|
|
|
16
16
|
[
|
|
17
17
|
"demo@mado.dev",
|
|
18
18
|
{
|
|
19
|
-
password: "
|
|
19
|
+
password: "demo123",
|
|
20
20
|
user: {
|
|
21
21
|
id: "u_demo",
|
|
22
22
|
email: "demo@mado.dev",
|
|
23
23
|
roles: ["user"],
|
|
24
|
-
permissions: ["billing.read"],
|
|
24
|
+
permissions: ["billing.read", "billing.invoices.pay"],
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
],
|
|
@@ -76,6 +76,7 @@ function devApiMock(): Plugin {
|
|
|
76
76
|
if (url === "/api/auth/me" && req.method === "GET") {
|
|
77
77
|
if (!token) return json(res, 401, { error: "unauthenticated" });
|
|
78
78
|
const entry = users.values().next().value;
|
|
79
|
+
if (!entry) return json(res, 500, { error: "mock_user_missing" });
|
|
79
80
|
return json(res, 200, entry.user);
|
|
80
81
|
}
|
|
81
82
|
if (url === "/api/auth/logout" && req.method === "POST") {
|
|
@@ -110,6 +111,9 @@ function devApiMock(): Plugin {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
export default defineConfig({
|
|
114
|
+
resolve: {
|
|
115
|
+
tsconfigPaths: true,
|
|
116
|
+
},
|
|
113
117
|
plugins: [
|
|
114
118
|
devApiMock(),
|
|
115
119
|
mado({
|
|
@@ -125,7 +129,4 @@ export default defineConfig({
|
|
|
125
129
|
// site: "https://your-app.example",
|
|
126
130
|
}),
|
|
127
131
|
],
|
|
128
|
-
css: {
|
|
129
|
-
transformer: "lightningcss",
|
|
130
|
-
},
|
|
131
132
|
});
|
package/dist/src/lazy.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lazy() — deferred module loading with a reactive placeholder.
|
|
3
|
-
*
|
|
4
|
-
* Why: heavy components (charts, code editors, modals)
|
|
5
|
-
* don't need to be loaded on startup. lazy() gives a TemplateResult function
|
|
6
|
-
* that returns a fallback until loaded, then the real template.
|
|
7
|
-
*
|
|
8
|
-
* const Chart = lazy(
|
|
9
|
-
* () => import('./components/chart.js'),
|
|
10
|
-
* { fallback: () => html`<x-spinner/>` },
|
|
11
|
-
* );
|
|
12
|
-
*
|
|
13
|
-
* html`<div>${Chart({ data })}</div>`
|
|
14
|
-
*
|
|
15
|
-
* Module contract: must default-export a function
|
|
16
|
-
* (props) => TemplateResult.
|
|
17
|
-
*
|
|
18
|
-
* Loading is cached (one import() per loader reference).
|
|
19
|
-
*/
|
|
20
|
-
import type { TemplateResult } from "./html/template-types.js";
|
|
21
|
-
export interface LazyOptions<P> {
|
|
22
|
-
/** What to show while the module is loading. */
|
|
23
|
-
fallback?: (props: P) => TemplateResult;
|
|
24
|
-
/** What to show if the import failed. Default — empty string. */
|
|
25
|
-
error?: (err: Error, props: P) => TemplateResult;
|
|
26
|
-
}
|
|
27
|
-
type Renderer<P> = (props: P) => TemplateResult;
|
|
28
|
-
/**
|
|
29
|
-
* Create a lazy component.
|
|
30
|
-
* Takes a dynamic import, returns a render function.
|
|
31
|
-
*
|
|
32
|
-
* const Modal = lazy(() => import('./modal.js'));
|
|
33
|
-
* html`${open() ? Modal({ onClose }) : null}`
|
|
34
|
-
*/
|
|
35
|
-
export declare function lazy<P = unknown>(loader: () => Promise<{
|
|
36
|
-
default: Renderer<P>;
|
|
37
|
-
}>, options?: LazyOptions<P>): (props: P) => TemplateResult;
|
|
38
|
-
export {};
|
package/dist/src/lazy.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lazy() — deferred module loading with a reactive placeholder.
|
|
3
|
-
*
|
|
4
|
-
* Why: heavy components (charts, code editors, modals)
|
|
5
|
-
* don't need to be loaded on startup. lazy() gives a TemplateResult function
|
|
6
|
-
* that returns a fallback until loaded, then the real template.
|
|
7
|
-
*
|
|
8
|
-
* const Chart = lazy(
|
|
9
|
-
* () => import('./components/chart.js'),
|
|
10
|
-
* { fallback: () => html`<x-spinner/>` },
|
|
11
|
-
* );
|
|
12
|
-
*
|
|
13
|
-
* html`<div>${Chart({ data })}</div>`
|
|
14
|
-
*
|
|
15
|
-
* Module contract: must default-export a function
|
|
16
|
-
* (props) => TemplateResult.
|
|
17
|
-
*
|
|
18
|
-
* Loading is cached (one import() per loader reference).
|
|
19
|
-
*/
|
|
20
|
-
import { signal } from "./signal.js";
|
|
21
|
-
import { html } from "./html/template.js";
|
|
22
|
-
const cache = new WeakMap();
|
|
23
|
-
/**
|
|
24
|
-
* Create a lazy component.
|
|
25
|
-
* Takes a dynamic import, returns a render function.
|
|
26
|
-
*
|
|
27
|
-
* const Modal = lazy(() => import('./modal.js'));
|
|
28
|
-
* html`${open() ? Modal({ onClose }) : null}`
|
|
29
|
-
*/
|
|
30
|
-
export function lazy(loader, options = {}) {
|
|
31
|
-
return (props) => {
|
|
32
|
-
// One signal trigger per call instance; the html binder will resubscribe
|
|
33
|
-
// when the state changes.
|
|
34
|
-
const trig = signal(0);
|
|
35
|
-
const state = ensureLoaded(loader);
|
|
36
|
-
if (state.state === "loading") {
|
|
37
|
-
// subscribe: when state transitions to ready/error, trigger trig
|
|
38
|
-
const wait = waitFor(loader);
|
|
39
|
-
wait.then(() => trig.update((n) => n + 1), () => trig.update((n) => n + 1));
|
|
40
|
-
}
|
|
41
|
-
return html `${() => {
|
|
42
|
-
trig(); // subscription
|
|
43
|
-
const s = ensureLoaded(loader);
|
|
44
|
-
if (s.state === "ready" && s.renderer)
|
|
45
|
-
return s.renderer(props);
|
|
46
|
-
if (s.state === "error" && s.err) {
|
|
47
|
-
return options.error?.(s.err, props) ?? "";
|
|
48
|
-
}
|
|
49
|
-
return options.fallback?.(props) ?? "";
|
|
50
|
-
}}`;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function ensureLoaded(loader) {
|
|
54
|
-
const existing = cache.get(loader);
|
|
55
|
-
if (existing)
|
|
56
|
-
return existing;
|
|
57
|
-
const fresh = { state: "loading" };
|
|
58
|
-
cache.set(loader, fresh);
|
|
59
|
-
loader().then((mod) => {
|
|
60
|
-
fresh.state = "ready";
|
|
61
|
-
fresh.renderer = mod.default;
|
|
62
|
-
}, (err) => {
|
|
63
|
-
fresh.state = "error";
|
|
64
|
-
fresh.err = err instanceof Error ? err : new Error(String(err));
|
|
65
|
-
});
|
|
66
|
-
return fresh;
|
|
67
|
-
}
|
|
68
|
-
function waitFor(loader) {
|
|
69
|
-
// return the same Promise as ensureLoaded — otherwise we'd create a new one.
|
|
70
|
-
// The browser actually caches the same module, so the second call returns instantly.
|
|
71
|
-
return loader();
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=lazy.js.map
|
package/dist/src/lazy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../src/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAkB1C,MAAM,KAAK,GAAG,IAAI,OAAO,EAA8B,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAClB,MAA+C,EAC/C,UAA0B,EAAE;IAE5B,OAAO,CAAC,KAAQ,EAAE,EAAE;QAClB,yEAAyE;QACzE,0BAA0B;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,KAAK,GAAG,YAAY,CAAI,MAAM,CAAC,CAAC;QAEtC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC9B,iEAAiE;YACjE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,CACP,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAC/B,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAChC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAA,GAAG,GAAG,EAAE;YACjB,IAAI,EAAE,CAAC,CAAC,eAAe;YACvB,MAAM,CAAC,GAAG,YAAY,CAAI,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;gBACjC,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAC7C,CAAC;YACD,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC,EAAE,CAAC;IACN,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,MAA+C;IAE/C,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAA2B,CAEzC,CAAC;IACd,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,KAAK,GAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACjD,KAAK,CAAC,GAAG,CAAC,MAA2B,EAAE,KAA2B,CAAC,CAAC;IACpE,MAAM,EAAE,CAAC,IAAI,CACX,CAAC,GAAG,EAAE,EAAE;QACN,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;QACtB,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC;IAC/B,CAAC,EACD,CAAC,GAAY,EAAE,EAAE;QACf,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;QACtB,KAAK,CAAC,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,CAAC,CACF,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CACd,MAA+C;IAE/C,6EAA6E;IAC7E,qFAAqF;IACrF,OAAO,MAAM,EAAE,CAAC;AAClB,CAAC"}
|
package/scripts/bake.mjs
DELETED
package/scripts/docs-lint.mjs
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Docs lint: refuses to ship documentation that still uses the legacy
|
|
3
|
-
// vocabulary the 0.12 release replaced. Active reference docs, README,
|
|
4
|
-
// llms.txt, AGENTS.md, CONTRIBUTING.md, TODO.md and the starter READMEs
|
|
5
|
-
// must use the new terms; migration guides, CHANGELOG, release notes
|
|
6
|
-
// and ADRs are allowed to mention the old names by name so users can
|
|
7
|
-
// find them.
|
|
8
|
-
|
|
9
|
-
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
10
|
-
import { dirname, join, resolve } from "node:path";
|
|
11
|
-
import { fileURLToPath } from "node:url";
|
|
12
|
-
|
|
13
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
const REPO_ROOT = resolve(__dirname, "..");
|
|
15
|
-
|
|
16
|
-
// Phrases that MUST disappear from current docs/README/llms/AGENTS. They
|
|
17
|
-
// remain legal inside the allow-listed contexts below.
|
|
18
|
-
const FORBIDDEN = [
|
|
19
|
-
// Page API renamed from `bake` to `static`.
|
|
20
|
-
{ pattern: /\bpage\.bake\b/, replacement: "page.static" },
|
|
21
|
-
{ pattern: /\bbake\.paths\b/, replacement: "static.paths" },
|
|
22
|
-
{ pattern: /\bbake\.data\b/, replacement: "static.initialData" },
|
|
23
|
-
{ pattern: /\bbake\.revalidate\b/, replacement: "drop; no revalidate API" },
|
|
24
|
-
|
|
25
|
-
// CLI renamed from `bake` to `static`.
|
|
26
|
-
{ pattern: /\bmado bake\b/, replacement: "mado static" },
|
|
27
|
-
{ pattern: /\bnpm run bake\b/, replacement: "npm run release" },
|
|
28
|
-
|
|
29
|
-
// Output / marker shape changed.
|
|
30
|
-
{ pattern: /\bout\/baked\b/, replacement: "out/<route>/index.html" },
|
|
31
|
-
{ pattern: /#bake\b/, replacement: "data-mado-static-data" },
|
|
32
|
-
|
|
33
|
-
// Old "Smart Static (`bake`)" headline.
|
|
34
|
-
{ pattern: /Smart Static \(`bake`\)/, replacement: "Static snapshots (`mado static`)" },
|
|
35
|
-
|
|
36
|
-
// Old transport / renderer claims.
|
|
37
|
-
{ pattern: /No Vite required/i, replacement: "drop the phrase; Vite is the canonical transport" },
|
|
38
|
-
{ pattern: /\bNo Chromium needed\b/i, replacement: "drop the phrase; mado static REQUIRES Chromium" },
|
|
39
|
-
// `linkedom` is also a legitimate Node-side test helper (the framework
|
|
40
|
-
// uses it in test/router/* for DOM unit tests). We only flag the
|
|
41
|
-
// phrases that mis-described the snapshot pipeline as a linkedom
|
|
42
|
-
// renderer.
|
|
43
|
-
{ pattern: /linkedom (?:as|is) (?:the |a )?(?:static|snapshot|production) renderer/i,
|
|
44
|
-
replacement: "drop the claim; capture uses Playwright/Chromium" },
|
|
45
|
-
{ pattern: /linkedom-?based renderer/i,
|
|
46
|
-
replacement: "drop the claim; capture uses Playwright/Chromium" },
|
|
47
|
-
{ pattern: /server-rendered snapshot/i, replacement: "browser-rendered snapshot" },
|
|
48
|
-
{ pattern: /\bmeta[- ]shell\b/i, replacement: "static snapshot" },
|
|
49
|
-
|
|
50
|
-
// Old positioning.
|
|
51
|
-
{
|
|
52
|
-
pattern: /SEO-heavy public sites are not supported/i,
|
|
53
|
-
replacement: "drop the phrase — Mado now snapshots public sites",
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
pattern: /\binternal tools only\b/i,
|
|
57
|
-
replacement: "drop the phrase — Mado is for sites and apps",
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
pattern: /SPA framework for internal tools/i,
|
|
61
|
-
replacement: "drop the phrase — Mado is for sites and apps",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
pattern: /shadow:\s*false[^.\n]*SEO/i,
|
|
65
|
-
replacement: "drop the recommendation; SEO is handled by snapshots",
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
// Old pre-Vite transport language.
|
|
69
|
-
{ pattern: /\btsc[- ]only\b/i, replacement: "drop the phrase — Vite is the canonical transport" },
|
|
70
|
-
{ pattern: /\bno bundler\b/i, replacement: "drop the phrase — Vite is the canonical bundler" },
|
|
71
|
-
{ pattern: /\btsc\s*(?:→|->)+\s*browser\b/i,
|
|
72
|
-
replacement: "drop the phrase — generated apps go through Vite" },
|
|
73
|
-
{ pattern: /\bimport[\s-]?map(?:s)?\b/i, replacement: "drop the phrase — apps use Vite, not import maps" },
|
|
74
|
-
|
|
75
|
-
// Old dev / static / edge claims.
|
|
76
|
-
{ pattern: /SSE[- ]?reload/i, replacement: "drop the phrase — dev uses Vite HMR" },
|
|
77
|
-
{ pattern: /\bedge[- ]prerender\b/i, replacement: "drop the phrase — capture is `mado static` only" },
|
|
78
|
-
|
|
79
|
-
// Old doc filenames in active docs (the migration table in
|
|
80
|
-
// docs/en/README.md is allow-listed via docs-lint:allow-legacy-mention
|
|
81
|
-
// markers around it if needed).
|
|
82
|
-
{ pattern: /\b03-static-bake\.md\b/, replacement: "15-static-snapshots.md" },
|
|
83
|
-
{ pattern: /\b09-shadow-vs-light-dom\.md\b/, replacement: "10-pages-and-components.md" },
|
|
84
|
-
{ pattern: /\b10-app-architecture\.md\b/, replacement: "16-app-architecture.md" },
|
|
85
|
-
{ pattern: /\b13-deployment\.md\b/, replacement: "20-deployment.md" },
|
|
86
|
-
{ pattern: /\b16-bake-cookbook\.md\b/, replacement: "23-cookbook.md" },
|
|
87
|
-
{ pattern: /\b18-api-freeze-map\.md\b/, replacement: "30-api-freeze-map.md" },
|
|
88
|
-
{ pattern: /\b19-reactivity-ordering\.md\b/, replacement: "31-reactivity-ordering.md" },
|
|
89
|
-
{ pattern: /\b20-v1-stability\.md\b/, replacement: "32-v1-stability.md" },
|
|
90
|
-
{ pattern: /\b07-llm-pitfalls\.md\b/, replacement: "40-llm-guide.md" },
|
|
91
|
-
{ pattern: /\b08-llm-zero-history-test\.md\b/, replacement: "40-llm-guide.md" },
|
|
92
|
-
];
|
|
93
|
-
|
|
94
|
-
const ALLOW_LISTED = [
|
|
95
|
-
/(^|\/)CHANGELOG\.md$/,
|
|
96
|
-
/(^|\/)docs\/architecture\/adr\//,
|
|
97
|
-
/(^|\/)docs\/.+migration/i,
|
|
98
|
-
/(^|\/)docs\/.+v1-stability/i,
|
|
99
|
-
/(^|\/)scripts\/docs-lint\.mjs$/,
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
// Files / trees that must stay on-message about the post-0.12 API. New
|
|
103
|
-
// roots must be added here AND covered by the CI step.
|
|
104
|
-
const ROOTS = [
|
|
105
|
-
"README.md",
|
|
106
|
-
"AGENTS.md",
|
|
107
|
-
"llms.txt",
|
|
108
|
-
"CONTRIBUTING.md",
|
|
109
|
-
"TODO.md",
|
|
110
|
-
"docs/README.md",
|
|
111
|
-
"docs/en",
|
|
112
|
-
"starters/default/README.md",
|
|
113
|
-
"starters/modular/README.md",
|
|
114
|
-
];
|
|
115
|
-
|
|
116
|
-
let errors = 0;
|
|
117
|
-
|
|
118
|
-
for (const root of ROOTS) {
|
|
119
|
-
const full = join(REPO_ROOT, root);
|
|
120
|
-
try {
|
|
121
|
-
statSync(full);
|
|
122
|
-
} catch {
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
scan(full);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (errors > 0) {
|
|
129
|
-
console.error(`\n[docs-lint] ${errors} forbidden term(s) in current docs.`);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
console.log("[docs-lint] OK");
|
|
133
|
-
|
|
134
|
-
function scan(path) {
|
|
135
|
-
const stat = statSync(path);
|
|
136
|
-
if (stat.isDirectory()) {
|
|
137
|
-
for (const entry of readdirSync(path)) scan(join(path, entry));
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (!path.endsWith(".md") && !path.endsWith(".txt")) return;
|
|
141
|
-
const rel = path.slice(REPO_ROOT.length + 1);
|
|
142
|
-
if (ALLOW_LISTED.some((rx) => rx.test(rel))) return;
|
|
143
|
-
|
|
144
|
-
const body = readFileSync(path, "utf8");
|
|
145
|
-
const lines = body.split("\n");
|
|
146
|
-
let inIgnoreBlock = false;
|
|
147
|
-
for (let i = 0; i < lines.length; i++) {
|
|
148
|
-
const line = lines[i];
|
|
149
|
-
// Block-scoped allowance: paragraphs that teach LLMs which names
|
|
150
|
-
// are obsolete must be free to mention those names verbatim.
|
|
151
|
-
// <!-- docs-lint:allow-legacy-mention -->
|
|
152
|
-
// ...legacy terms...
|
|
153
|
-
// <!-- /docs-lint:allow-legacy-mention -->
|
|
154
|
-
if (line.includes("docs-lint:allow-legacy-mention")) {
|
|
155
|
-
inIgnoreBlock = !line.includes("/docs-lint:allow-legacy-mention");
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
if (inIgnoreBlock) continue;
|
|
159
|
-
|
|
160
|
-
for (const rule of FORBIDDEN) {
|
|
161
|
-
if (rule.pattern.test(line)) {
|
|
162
|
-
errors++;
|
|
163
|
-
console.error(
|
|
164
|
-
`${rel}:${i + 1}: forbidden term matches /${rule.pattern.source}/. ` +
|
|
165
|
-
`Replace with: ${rule.replacement}`,
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { execFile } from "node:child_process";
|
|
4
|
-
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
import { basename, join, resolve } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { promisify } from "node:util";
|
|
9
|
-
|
|
10
|
-
const exec = promisify(execFile);
|
|
11
|
-
const repoRoot = resolve(fileURLToPath(new URL("..", import.meta.url)));
|
|
12
|
-
const tempRoot = await mkdtemp(join(tmpdir(), "mado-package-smoke-"));
|
|
13
|
-
let tarball = "";
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const packed = await exec("npm", ["pack", "--silent"], { cwd: repoRoot });
|
|
17
|
-
tarball = resolve(repoRoot, packed.stdout.trim().split(/\s+/).at(-1) ?? "");
|
|
18
|
-
if (!tarball) throw new Error("[package-smoke] npm pack did not return a tarball");
|
|
19
|
-
|
|
20
|
-
const installRoot = join(tempRoot, "installed");
|
|
21
|
-
await mkdir(installRoot, { recursive: true });
|
|
22
|
-
await run("npm", ["install", tarball], { cwd: installRoot });
|
|
23
|
-
|
|
24
|
-
// Public-API surface smoke: prove the published tarball exposes the
|
|
25
|
-
// root entry, the devtools side-effect import and the Vite plugin,
|
|
26
|
-
// while still hiding internal subpaths behind `exports`.
|
|
27
|
-
await run(
|
|
28
|
-
process.execPath,
|
|
29
|
-
[
|
|
30
|
-
"--input-type=module",
|
|
31
|
-
"--eval",
|
|
32
|
-
`
|
|
33
|
-
import { html, signal, routeUrl, appBase } from "@madojs/mado";
|
|
34
|
-
import "@madojs/mado/devtools.js";
|
|
35
|
-
import { mado } from "@madojs/mado/vite";
|
|
36
|
-
if (typeof html !== "function" || typeof signal !== "function") {
|
|
37
|
-
throw new Error("public root import failed");
|
|
38
|
-
}
|
|
39
|
-
if (typeof routeUrl !== "function" || typeof appBase !== "string") {
|
|
40
|
-
throw new Error("routing helpers missing from public root");
|
|
41
|
-
}
|
|
42
|
-
if (typeof mado !== "function") throw new Error("vite plugin import failed");
|
|
43
|
-
try {
|
|
44
|
-
await import("@madojs/mado/lifecycle.js");
|
|
45
|
-
throw new Error("internal lifecycle subpath unexpectedly resolved");
|
|
46
|
-
} catch (err) {
|
|
47
|
-
if (err?.code !== "ERR_PACKAGE_PATH_NOT_EXPORTED") throw err;
|
|
48
|
-
}
|
|
49
|
-
`,
|
|
50
|
-
],
|
|
51
|
-
{ cwd: installRoot },
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
// We exercise BOTH published starters end-to-end:
|
|
55
|
-
//
|
|
56
|
-
// smoke-universal — `mado init` (default), npm install, typecheck,
|
|
57
|
-
// release. This is the path the README quick-start
|
|
58
|
-
// points new users to; if it ever breaks for a
|
|
59
|
-
// published tarball the first-run experience is
|
|
60
|
-
// broken.
|
|
61
|
-
//
|
|
62
|
-
// smoke-modular — `mado init --starter modular`, npm install,
|
|
63
|
-
// `mado new module`, release. Long-lived apps
|
|
64
|
-
// deploy this shape; the `mado new` generator
|
|
65
|
-
// also lives here.
|
|
66
|
-
//
|
|
67
|
-
// Each run uses MADO_SITE so static routes resolve canonical URLs,
|
|
68
|
-
// and points the starter at the freshly packed tarball through
|
|
69
|
-
// MADO_PACKAGE_SPEC so package.json doesn't reference an unpublished
|
|
70
|
-
// version.
|
|
71
|
-
|
|
72
|
-
await smokeStarter({
|
|
73
|
-
label: "universal",
|
|
74
|
-
appName: "smoke-universal",
|
|
75
|
-
initArgs: ["mado", "init", "smoke-universal"],
|
|
76
|
-
after: async (appRoot) => {
|
|
77
|
-
await run("npm", ["run", "typecheck"], { cwd: appRoot });
|
|
78
|
-
await run("npm", ["run", "release"], {
|
|
79
|
-
cwd: appRoot,
|
|
80
|
-
env: { ...process.env, MADO_SITE: "https://package-smoke.test" },
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
installRoot,
|
|
84
|
-
tarball,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
await smokeStarter({
|
|
88
|
-
label: "modular",
|
|
89
|
-
appName: "smoke-modular",
|
|
90
|
-
initArgs: ["mado", "init", "smoke-modular", "--starter", "modular"],
|
|
91
|
-
after: async (appRoot) => {
|
|
92
|
-
await run("npm", ["run", "new", "--", "module", "smoke"], {
|
|
93
|
-
cwd: appRoot,
|
|
94
|
-
});
|
|
95
|
-
await run("npm", ["run", "typecheck"], { cwd: appRoot });
|
|
96
|
-
await run("npm", ["run", "release"], {
|
|
97
|
-
cwd: appRoot,
|
|
98
|
-
env: { ...process.env, MADO_SITE: "https://package-smoke.test" },
|
|
99
|
-
});
|
|
100
|
-
},
|
|
101
|
-
installRoot,
|
|
102
|
-
tarball,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
console.log(`[package-smoke] ok ${basename(tarball)}`);
|
|
106
|
-
} finally {
|
|
107
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
108
|
-
if (tarball) await rm(tarball, { force: true });
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function smokeStarter({ label, appName, initArgs, after, installRoot, tarball }) {
|
|
112
|
-
console.log(`[package-smoke] === ${label} starter ===`);
|
|
113
|
-
await run("npx", initArgs, {
|
|
114
|
-
cwd: installRoot,
|
|
115
|
-
env: { ...process.env, MADO_PACKAGE_SPEC: tarball },
|
|
116
|
-
});
|
|
117
|
-
const appRoot = join(installRoot, appName);
|
|
118
|
-
await run("npm", ["install"], { cwd: appRoot });
|
|
119
|
-
await after(appRoot);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async function run(cmd, args, options) {
|
|
123
|
-
console.log(`[package-smoke] ${cmd} ${args.join(" ")}`);
|
|
124
|
-
try {
|
|
125
|
-
await exec(cmd, args, {
|
|
126
|
-
cwd: options.cwd,
|
|
127
|
-
env: options.env ?? process.env,
|
|
128
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
129
|
-
});
|
|
130
|
-
} catch (err) {
|
|
131
|
-
if (err.stdout) process.stdout.write(err.stdout);
|
|
132
|
-
if (err.stderr) process.stderr.write(err.stderr);
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
135
|
-
}
|