@madojs/mado 0.11.1 → 0.13.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 +116 -32
- package/CHANGELOG.md +216 -1
- package/README.md +158 -173
- package/dist/src/component.d.ts +6 -3
- package/dist/src/component.d.ts.map +1 -0
- package/dist/src/component.js +163 -36
- 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 +34 -5
- 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 +7 -6
- package/dist/src/head.d.ts.map +1 -0
- package/dist/src/head.js +8 -7
- 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 +4 -5
- package/dist/src/html/parser.d.ts.map +1 -0
- package/dist/src/html/parser.js +64 -15
- 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 +102 -13
- package/dist/src/html/template.js.map +1 -1
- package/dist/src/index.d.ts +15 -12
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -10
- 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 +63 -28
- package/dist/src/page.d.ts.map +1 -0
- package/dist/src/page.js +5 -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 +128 -50
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/base.d.ts +66 -0
- package/dist/src/router/base.d.ts.map +1 -0
- package/dist/src/router/base.js +168 -0
- package/dist/src/router/base.js.map +1 -0
- 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 +156 -171
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/match.d.ts +17 -2
- package/dist/src/router/match.d.ts.map +1 -0
- package/dist/src/router/match.js +60 -6
- 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 +58 -9
- 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 +82 -0
- package/dist/src/static-runtime.d.ts.map +1 -0
- package/dist/src/static-runtime.js +209 -0
- package/dist/src/static-runtime.js.map +1 -0
- package/dist/src/vite/index.d.ts +32 -3
- package/dist/src/vite/index.d.ts.map +1 -0
- package/dist/src/vite/index.js +49 -17
- package/dist/src/vite/index.js.map +1 -1
- package/docs/README.md +5 -8
- package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
- package/docs/architecture/v1-roadmap.md +19 -0
- package/docs/en/00-the-mado-way.md +1 -1
- package/docs/en/01-quickstart.md +183 -0
- package/docs/en/10-pages-and-components.md +279 -0
- package/docs/en/11-templates-and-signals.md +211 -0
- package/docs/en/12-routing.md +229 -0
- package/docs/en/13-data.md +227 -0
- package/docs/en/14-forms.md +91 -0
- package/docs/en/15-static-snapshots.md +181 -0
- package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +56 -4
- package/docs/en/{13-deployment.md → 20-deployment.md} +79 -17
- package/docs/en/{15-error-handling.md → 21-error-handling.md} +9 -6
- package/docs/en/{14-testing.md → 22-testing.md} +6 -5
- package/docs/en/23-cookbook.md +292 -0
- package/docs/en/24-devtools-and-diagnostics.md +45 -0
- package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +17 -9
- package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +5 -5
- package/docs/en/33-migration-0.12-0.13.md +56 -0
- package/docs/en/40-llm-guide.md +774 -0
- package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +28 -25
- package/docs/en/{05-why-mado.md → 42-why-mado.md} +3 -3
- package/docs/en/README.md +99 -27
- package/docs/recipes/nginx/Containerfile +26 -0
- package/docs/recipes/nginx/nginx.conf +42 -0
- package/llms.txt +263 -210
- package/package.json +51 -23
- package/scripts/clean.mjs +8 -0
- package/scripts/cli/generate.mjs +57 -10
- package/scripts/cli/help.mjs +13 -5
- package/scripts/cli/index.mjs +31 -7
- package/scripts/cli/init.mjs +19 -19
- package/scripts/cli/release.mjs +38 -83
- package/scripts/cli/run.mjs +5 -3
- package/scripts/logger.mjs +117 -0
- package/scripts/output-guard.mjs +128 -0
- package/scripts/preview.mjs +105 -24
- package/scripts/static/browser.mjs +695 -0
- package/scripts/static/discover.mjs +284 -0
- package/scripts/static/output.mjs +141 -0
- package/scripts/static/serialize.mjs +212 -0
- package/scripts/static/server.mjs +167 -0
- package/scripts/static.mjs +205 -0
- package/starters/default/README.md +57 -55
- package/starters/default/package.json +6 -12
- package/starters/default/src/app.routes.ts +20 -33
- package/starters/default/src/components/feature-card.component.ts +40 -0
- package/starters/default/src/components/live-counter.component.ts +57 -0
- package/starters/default/src/content/guides.ts +55 -0
- package/starters/default/src/main.ts +9 -13
- package/starters/default/src/pages/app.page.ts +41 -0
- package/starters/default/src/pages/guide.page.ts +40 -0
- package/starters/default/src/pages/home.page.ts +49 -0
- package/starters/default/src/pages/not-found.page.ts +18 -0
- package/starters/default/src/styles/document.css +39 -0
- package/starters/default/src/styles/reset.css +37 -0
- package/starters/default/src/styles/tokens.css +30 -0
- package/starters/default/src/styles.d.ts +3 -1
- package/starters/default/src/vite-env.d.ts +1 -1
- package/starters/default/tsconfig.node.json +13 -0
- package/starters/default/vite.config.ts +14 -4
- package/starters/modular/README.md +142 -0
- package/starters/modular/index.html +13 -0
- package/starters/modular/package.json +30 -0
- package/starters/modular/src/app.routes.ts +39 -0
- package/starters/{default → modular}/src/layouts/app-shell.layout.ts +9 -7
- package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
- package/starters/modular/src/main.ts +16 -0
- package/starters/{default → modular}/src/modules/auth/login.page.ts +5 -12
- package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +3 -4
- package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +4 -4
- package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
- package/starters/modular/src/modules/home/not-found.page.ts +14 -0
- package/starters/{default → modular}/src/shared/styles/reset.css +21 -1
- package/starters/modular/src/styles.d.ts +1 -0
- package/starters/modular/src/vite-env.d.ts +1 -0
- package/starters/modular/tsconfig.json +33 -0
- package/starters/modular/tsconfig.node.json +13 -0
- package/starters/modular/vite.config.ts +132 -0
- package/TODO.md +0 -79
- package/dist/src/lazy.d.ts +0 -38
- package/dist/src/lazy.js +0 -73
- package/dist/src/lazy.js.map +0 -1
- package/docs/en/01-routing.md +0 -152
- package/docs/en/02-project-layout.md +0 -124
- package/docs/en/03-static-bake.md +0 -249
- package/docs/en/04-ide-setup.md +0 -162
- package/docs/en/07-llm-pitfalls.md +0 -724
- package/docs/en/08-llm-zero-history-test.md +0 -56
- package/docs/en/09-shadow-vs-light-dom.md +0 -174
- package/docs/en/11-layouts.md +0 -113
- package/docs/en/12-auth-and-api.md +0 -124
- package/docs/en/16-bake-cookbook.md +0 -100
- package/docs/en/17-shadow-dom-forms.md +0 -192
- package/docs/fr/00-the-mado-way.md +0 -85
- package/docs/fr/01-routing.md +0 -120
- package/docs/fr/02-project-layout.md +0 -84
- package/docs/fr/03-static-bake.md +0 -289
- package/docs/fr/04-ide-setup.md +0 -162
- package/docs/fr/05-why-mado.md +0 -193
- package/docs/fr/06-for-backenders.md +0 -438
- package/docs/fr/07-llm-pitfalls.md +0 -625
- package/docs/fr/08-llm-zero-history-test.md +0 -38
- package/docs/fr/09-shadow-vs-light-dom.md +0 -65
- package/docs/fr/10-app-architecture.md +0 -138
- package/docs/fr/11-layouts.md +0 -47
- package/docs/fr/12-auth-and-api.md +0 -76
- package/docs/fr/13-deployment.md +0 -57
- package/docs/fr/14-testing.md +0 -41
- package/docs/fr/15-error-handling.md +0 -50
- package/docs/fr/16-bake-cookbook.md +0 -88
- package/docs/fr/17-shadow-dom-forms.md +0 -196
- package/docs/fr/18-api-freeze-map.md +0 -63
- package/docs/fr/19-reactivity-ordering.md +0 -97
- package/docs/fr/20-v1-stability.md +0 -88
- package/docs/fr/README.md +0 -27
- package/docs/ru/00-the-mado-way.md +0 -84
- package/docs/ru/01-routing.md +0 -119
- package/docs/ru/02-project-layout.md +0 -84
- package/docs/ru/03-static-bake.md +0 -250
- package/docs/ru/04-ide-setup.md +0 -144
- package/docs/ru/05-why-mado.md +0 -193
- package/docs/ru/06-for-backenders.md +0 -428
- package/docs/ru/07-llm-pitfalls.md +0 -624
- package/docs/ru/08-llm-zero-history-test.md +0 -57
- package/docs/ru/09-shadow-vs-light-dom.md +0 -63
- package/docs/ru/10-app-architecture.md +0 -152
- package/docs/ru/11-layouts.md +0 -47
- package/docs/ru/12-auth-and-api.md +0 -75
- package/docs/ru/13-deployment.md +0 -66
- package/docs/ru/14-testing.md +0 -50
- package/docs/ru/15-error-handling.md +0 -56
- package/docs/ru/16-bake-cookbook.md +0 -95
- package/docs/ru/17-shadow-dom-forms.md +0 -193
- package/docs/ru/18-api-freeze-map.md +0 -64
- package/docs/ru/19-reactivity-ordering.md +0 -95
- package/docs/ru/20-v1-stability.md +0 -82
- package/docs/ru/README.md +0 -25
- package/docs/uk/00-the-mado-way.md +0 -82
- package/docs/uk/01-routing.md +0 -76
- package/docs/uk/02-project-layout.md +0 -73
- package/docs/uk/03-static-bake.md +0 -48
- package/docs/uk/04-ide-setup.md +0 -26
- package/docs/uk/05-why-mado.md +0 -34
- package/docs/uk/06-for-backenders.md +0 -55
- package/docs/uk/07-llm-pitfalls.md +0 -145
- package/docs/uk/08-llm-zero-history-test.md +0 -34
- package/docs/uk/09-shadow-vs-light-dom.md +0 -58
- package/docs/uk/10-app-architecture.md +0 -97
- package/docs/uk/11-layouts.md +0 -47
- package/docs/uk/12-auth-and-api.md +0 -70
- package/docs/uk/13-deployment.md +0 -40
- package/docs/uk/14-testing.md +0 -34
- package/docs/uk/15-error-handling.md +0 -32
- package/docs/uk/16-bake-cookbook.md +0 -36
- package/docs/uk/17-shadow-dom-forms.md +0 -193
- package/docs/uk/18-api-freeze-map.md +0 -61
- package/docs/uk/19-reactivity-ordering.md +0 -95
- package/docs/uk/20-v1-stability.md +0 -83
- package/docs/uk/README.md +0 -27
- package/scripts/bake.mjs +0 -570
- package/scripts/package-smoke.mjs +0 -77
- package/scripts/release-notes.mjs +0 -66
- package/scripts/size-budget.mjs +0 -91
- package/starters/default/src/modules/home/not-found.page.ts +0 -11
- package/starters/default/src/shared/ui/x-button.component.ts +0 -49
- /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
- /package/starters/{default → modular}/.editorconfig +0 -0
- /package/starters/{default → modular}/eslint.config.mjs +0 -0
- /package/starters/{default → modular}/public/favicon.svg +0 -0
- /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
- /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
- /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
- /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
- /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
- /package/starters/{default → modular}/src/shared/ui/x-spinner.component.ts +0 -0
package/scripts/bake.mjs
DELETED
|
@@ -1,570 +0,0 @@
|
|
|
1
|
-
// Smart Static: bake HTML for pages whose `page({ bake })` is set.
|
|
2
|
-
//
|
|
3
|
-
// Usage:
|
|
4
|
-
// mado bake
|
|
5
|
-
// mado bake --entry src/routes.ts --template index.html --out out
|
|
6
|
-
// mado bake --base-url https://example.com
|
|
7
|
-
//
|
|
8
|
-
// Defaults:
|
|
9
|
-
// entry: src/app.routes.ts, then src/routes.ts
|
|
10
|
-
// template: index.html
|
|
11
|
-
// out: out/
|
|
12
|
-
//
|
|
13
|
-
// What it does:
|
|
14
|
-
// 1. Loads `entry` (routes module) through Vite SSR/module loading.
|
|
15
|
-
// 2. For every route whose page has `bake`:
|
|
16
|
-
// a) gets params via `bake.paths()`,
|
|
17
|
-
// b) gets data per params via `bake.data(params)`,
|
|
18
|
-
// c) renders the TemplateResult to an HTML string (no browser),
|
|
19
|
-
// d) materializes head() into <meta>/<link>/<script type=json-ld>,
|
|
20
|
-
// e) inlines baked data in <script id="bake" type="application/json">,
|
|
21
|
-
// f) writes <out>/<path>/index.html.
|
|
22
|
-
// 3. Generates <out>/sitemap.xml.
|
|
23
|
-
//
|
|
24
|
-
// Context awareness:
|
|
25
|
-
// - In app-mode (default outside the framework repository) the bundler
|
|
26
|
-
// resolves `@madojs/mado` from node_modules normally.
|
|
27
|
-
// - In repo-mode (the framework repository itself) it aliases
|
|
28
|
-
// `@madojs/mado` → ./src/index.ts so the framework can dogfood itself.
|
|
29
|
-
//
|
|
30
|
-
// Required dev deps: linkedom, vite. We print a clear error if missing.
|
|
31
|
-
|
|
32
|
-
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
33
|
-
import { existsSync, writeSync } from "node:fs";
|
|
34
|
-
import { join, dirname, resolve } from "node:path";
|
|
35
|
-
|
|
36
|
-
import { detectContext, parseFlags, resolveProjectPath } from "./_config.mjs";
|
|
37
|
-
|
|
38
|
-
// ---------- Resolve options from config + flags + env ----------
|
|
39
|
-
|
|
40
|
-
const { flags } = parseFlags(process.argv.slice(2));
|
|
41
|
-
const PROJECT_ROOT = resolve(process.cwd());
|
|
42
|
-
const CONTEXT = detectContext(PROJECT_ROOT);
|
|
43
|
-
const ENTRY = resolveProjectPath(
|
|
44
|
-
PROJECT_ROOT,
|
|
45
|
-
typeof flags.entry === "string" ? flags.entry : pickDefaultEntry(PROJECT_ROOT),
|
|
46
|
-
);
|
|
47
|
-
const TEMPLATE = resolveProjectPath(
|
|
48
|
-
PROJECT_ROOT,
|
|
49
|
-
typeof flags.template === "string" ? flags.template : "index.html",
|
|
50
|
-
);
|
|
51
|
-
const BASE_URL = typeof flags["base-url"] === "string" ? flags["base-url"] : "https://example.com";
|
|
52
|
-
const OUT_DIR = resolveProjectPath(
|
|
53
|
-
PROJECT_ROOT,
|
|
54
|
-
typeof flags.out === "string" ? flags.out : "out",
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
/** Write message to stderr and exit. Sync write keeps CI/execFile output reliable. */
|
|
58
|
-
function fatal(...msgs) {
|
|
59
|
-
writeSync(2, msgs.join("\n") + "\n");
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function error(...msgs) {
|
|
64
|
-
writeSync(2, msgs.join(" ") + "\n");
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!existsSync(ENTRY)) {
|
|
68
|
-
fatal(
|
|
69
|
-
`[bake] entry not found: ${ENTRY}`,
|
|
70
|
-
`[bake] expected src/app.routes.ts or src/routes.ts; pass --entry <file> to override`,
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
if (!existsSync(TEMPLATE)) {
|
|
74
|
-
fatal(
|
|
75
|
-
`[bake] template not found: ${TEMPLATE}`,
|
|
76
|
-
`[bake] expected index.html; pass --template <file> to override`,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ---------- Optional dependencies ----------
|
|
81
|
-
|
|
82
|
-
let parseHTML;
|
|
83
|
-
try {
|
|
84
|
-
({ parseHTML } = await import("linkedom"));
|
|
85
|
-
} catch {
|
|
86
|
-
fatal(
|
|
87
|
-
"[bake] package 'linkedom' is required.",
|
|
88
|
-
"[bake] Install it as a dev dependency in this project:",
|
|
89
|
-
"[bake] npm i -D linkedom vite",
|
|
90
|
-
"[bake] (vite is also required, see next check).",
|
|
91
|
-
"[bake] These are not bundled into @madojs/mado on purpose: bake is an",
|
|
92
|
-
"[bake] optional build step and we don't want to add transitive deps to",
|
|
93
|
-
"[bake] every Mado install.",
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let createViteServer;
|
|
98
|
-
try {
|
|
99
|
-
({ createServer: createViteServer } = await import("vite"));
|
|
100
|
-
} catch {
|
|
101
|
-
fatal(
|
|
102
|
-
"[bake] package 'vite' is required.",
|
|
103
|
-
"[bake] Install it as a dev dependency in this project:",
|
|
104
|
-
"[bake] npm i -D vite linkedom",
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ---------- DOM polyfills for Node ----------
|
|
109
|
-
//
|
|
110
|
-
// router.ts / component.ts / css.ts touch window/document/location/customElements
|
|
111
|
-
// at module top-level. Node has none, so install linkedom stubs before importing
|
|
112
|
-
// the app graph.
|
|
113
|
-
|
|
114
|
-
const baseHtml = await readFile(TEMPLATE, "utf8");
|
|
115
|
-
const { window: linkedomWindow } = parseHTML(baseHtml);
|
|
116
|
-
|
|
117
|
-
globalThis.window = linkedomWindow;
|
|
118
|
-
globalThis.document = linkedomWindow.document;
|
|
119
|
-
globalThis.location = new URL("http://localhost/");
|
|
120
|
-
globalThis.history = { pushState: () => { }, replaceState: () => { } };
|
|
121
|
-
globalThis.customElements = {
|
|
122
|
-
define: () => { },
|
|
123
|
-
get: () => undefined,
|
|
124
|
-
whenDefined: () => Promise.resolve(),
|
|
125
|
-
};
|
|
126
|
-
globalThis.HTMLElement = linkedomWindow.HTMLElement ?? class { };
|
|
127
|
-
globalThis.CSSStyleSheet = globalThis.CSSStyleSheet ?? class {
|
|
128
|
-
cssRules = [];
|
|
129
|
-
replaceSync() { }
|
|
130
|
-
};
|
|
131
|
-
globalThis.matchMedia = () => ({
|
|
132
|
-
matches: false,
|
|
133
|
-
addEventListener: () => { },
|
|
134
|
-
removeEventListener: () => { },
|
|
135
|
-
});
|
|
136
|
-
if (!globalThis.queueMicrotask) {
|
|
137
|
-
globalThis.queueMicrotask = (fn) => Promise.resolve().then(fn);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// ---------- Load the routes module through Vite ----------
|
|
141
|
-
//
|
|
142
|
-
// In repo-mode the framework dogfoods its own source; alias `@madojs/mado`
|
|
143
|
-
// to ./src/index.ts. In app-mode the package is resolved from node_modules.
|
|
144
|
-
|
|
145
|
-
const aliases = CONTEXT === "repo"
|
|
146
|
-
? { "@madojs/mado": resolve(PROJECT_ROOT, "src/index.ts") }
|
|
147
|
-
: {};
|
|
148
|
-
|
|
149
|
-
const viteServer = await createViteServer({
|
|
150
|
-
root: PROJECT_ROOT,
|
|
151
|
-
logLevel: "error",
|
|
152
|
-
server: { middlewareMode: true },
|
|
153
|
-
appType: "custom",
|
|
154
|
-
resolve: { alias: aliases },
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
let routesModule;
|
|
158
|
-
try {
|
|
159
|
-
routesModule = await viteServer.ssrLoadModule(toViteId(ENTRY));
|
|
160
|
-
} catch (err) {
|
|
161
|
-
await closeAndFatal(`[bake] failed to load ${ENTRY}: ${err.message}`);
|
|
162
|
-
}
|
|
163
|
-
const routeApi = routesModule.default;
|
|
164
|
-
|
|
165
|
-
if (!routeApi) {
|
|
166
|
-
await closeAndFatal(`[bake] ${ENTRY} must default-export routes({...})`);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Bake needs the source manifest (not the runtime RouterApi).
|
|
170
|
-
// routes.ts must therefore also `export const manifest = {...}`.
|
|
171
|
-
const manifest = routesModule.manifest;
|
|
172
|
-
if (!manifest) {
|
|
173
|
-
await closeAndFatal(
|
|
174
|
-
`[bake] ${ENTRY} must also \`export const manifest = {...}\` ` +
|
|
175
|
-
"(the same object passed to routes()).",
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// ---------- Main loop ----------
|
|
180
|
-
|
|
181
|
-
await mkdir(OUT_DIR, { recursive: true });
|
|
182
|
-
|
|
183
|
-
// Re-read template (already loaded for DOM polyfills, but we want a fresh copy
|
|
184
|
-
// per generated page so meta/link tags don't accumulate across iterations).
|
|
185
|
-
const TEMPLATE_HTML = baseHtml;
|
|
186
|
-
|
|
187
|
-
const sitemapEntries = [];
|
|
188
|
-
let total = 0;
|
|
189
|
-
let bakedErrors = 0;
|
|
190
|
-
let bakeablePages = 0;
|
|
191
|
-
const skippedNoBake = [];
|
|
192
|
-
|
|
193
|
-
for (const [pattern, entry] of Object.entries(manifest)) {
|
|
194
|
-
if (pattern === "*") continue;
|
|
195
|
-
|
|
196
|
-
const pg = await resolvePage(entry);
|
|
197
|
-
if (!pg) continue;
|
|
198
|
-
if (!pg.bake) {
|
|
199
|
-
skippedNoBake.push(pattern);
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
bakeablePages++;
|
|
203
|
-
|
|
204
|
-
console.log(`[bake] ${pattern}`);
|
|
205
|
-
|
|
206
|
-
let allParams;
|
|
207
|
-
try {
|
|
208
|
-
allParams = await pg.bake.paths();
|
|
209
|
-
} catch (err) {
|
|
210
|
-
error(`[bake] ${pattern}: bake.paths() failed:`, err.message);
|
|
211
|
-
bakedErrors++;
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
for (const params of allParams) {
|
|
216
|
-
const pathname = applyParams(pattern, params);
|
|
217
|
-
let data;
|
|
218
|
-
try {
|
|
219
|
-
data = await pg.bake.data(params);
|
|
220
|
-
} catch (err) {
|
|
221
|
-
error(`[bake] ${pathname}: bake.data() failed:`, err.message);
|
|
222
|
-
bakedErrors++;
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
const headMeta = pg.head ? pg.head(params, data) : {};
|
|
226
|
-
|
|
227
|
-
// Ensure <title> is always set in baked HTML. page.title is the primary
|
|
228
|
-
// source (string or function of params); head().title overrides it.
|
|
229
|
-
if (!headMeta.title && pg.title) {
|
|
230
|
-
headMeta.title = typeof pg.title === "function" ? pg.title(params) : pg.title;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const tpl = pg.view({
|
|
234
|
-
params,
|
|
235
|
-
data,
|
|
236
|
-
path: () => pathname,
|
|
237
|
-
child: null,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
let bodyHtml;
|
|
241
|
-
try {
|
|
242
|
-
bodyHtml = renderTemplate(tpl, { route: pattern });
|
|
243
|
-
} catch (err) {
|
|
244
|
-
error(`[bake] ${pathname}: render failed:`, err.message);
|
|
245
|
-
bakedErrors++;
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const finalHtml = buildHtml({
|
|
250
|
-
template: TEMPLATE_HTML,
|
|
251
|
-
bodyHtml,
|
|
252
|
-
head: headMeta,
|
|
253
|
-
bakedData: data,
|
|
254
|
-
revalidate: pg.bake.revalidate,
|
|
255
|
-
canonical: headMeta.canonical ?? `${BASE_URL}${pathname}`,
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
const file = join(
|
|
259
|
-
OUT_DIR,
|
|
260
|
-
pathname === "/" ? "/index.html" : `${pathname}/index.html`,
|
|
261
|
-
);
|
|
262
|
-
await mkdir(dirname(file), { recursive: true });
|
|
263
|
-
await writeFile(file, finalHtml);
|
|
264
|
-
total++;
|
|
265
|
-
sitemapEntries.push({ loc: `${BASE_URL}${pathname}`, changefreq: "weekly" });
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// ---------- Sitemap ----------
|
|
270
|
-
|
|
271
|
-
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
|
272
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
273
|
-
${sitemapEntries
|
|
274
|
-
.map(
|
|
275
|
-
(e) =>
|
|
276
|
-
` <url><loc>${escapeXml(e.loc)}</loc><changefreq>${e.changefreq}</changefreq></url>`,
|
|
277
|
-
)
|
|
278
|
-
.join("\n")}
|
|
279
|
-
</urlset>
|
|
280
|
-
`;
|
|
281
|
-
await writeFile(join(OUT_DIR, "sitemap.xml"), sitemap);
|
|
282
|
-
|
|
283
|
-
console.log(`[bake] done: ${total} pages + sitemap.xml → ${OUT_DIR}`);
|
|
284
|
-
if (bakedErrors > 0) {
|
|
285
|
-
await closeAndFatal(`[bake] ${bakedErrors} route(s) failed; see errors above.`);
|
|
286
|
-
}
|
|
287
|
-
// Loud diagnostic when the manifest exists but no page declares `bake`.
|
|
288
|
-
// Previously bake silently produced 0 pages + an empty sitemap and exited
|
|
289
|
-
// 0, which made `mado release` look successful while shipping no static
|
|
290
|
-
// HTML for crawlers. Fail loudly so the user notices.
|
|
291
|
-
if (bakeablePages === 0) {
|
|
292
|
-
error("");
|
|
293
|
-
error(
|
|
294
|
-
`[bake] WARNING: no page in ${ENTRY} declares \`bake: { paths, data }\`.`,
|
|
295
|
-
);
|
|
296
|
-
error(
|
|
297
|
-
`[bake] ${skippedNoBake.length} route(s) skipped: ${skippedNoBake
|
|
298
|
-
.slice(0, 6)
|
|
299
|
-
.join(", ")}${skippedNoBake.length > 6 ? ", …" : ""}`,
|
|
300
|
-
);
|
|
301
|
-
error("[bake] Add `bake` to at least one page (e.g. your landing route):");
|
|
302
|
-
error("[bake] export default page({");
|
|
303
|
-
error("[bake] view: …,");
|
|
304
|
-
error("[bake] bake: { paths: () => [{}], data: () => ({}) },");
|
|
305
|
-
error("[bake] });");
|
|
306
|
-
error(
|
|
307
|
-
"[bake] Without bake the build ships only the SPA shell — search engines",
|
|
308
|
-
);
|
|
309
|
-
error("[bake] and link previews see an empty <body>.");
|
|
310
|
-
// Exit non-zero so `mado release` halts and the user is forced to address
|
|
311
|
-
// it. If you intentionally have an SPA-only deploy, drop `mado bake` from
|
|
312
|
-
// the release pipeline (or set MADO_BAKE_ALLOW_EMPTY=1).
|
|
313
|
-
if (process.env.MADO_BAKE_ALLOW_EMPTY !== "1") {
|
|
314
|
-
await viteServer.close();
|
|
315
|
-
process.exit(1);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
await viteServer.close();
|
|
320
|
-
|
|
321
|
-
// ---------- Helpers ----------
|
|
322
|
-
|
|
323
|
-
async function resolvePage(entry) {
|
|
324
|
-
if (entry && entry._page === true) return entry;
|
|
325
|
-
if (typeof entry === "function") {
|
|
326
|
-
try {
|
|
327
|
-
const mod = await entry();
|
|
328
|
-
return mod?.default;
|
|
329
|
-
} catch (e) {
|
|
330
|
-
console.warn("[bake] failed to load route:", e.message);
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
return null;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function toViteId(path) {
|
|
338
|
-
return path.split("\\").join("/");
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function pickDefaultEntry(projectRoot) {
|
|
342
|
-
const appRoutes = "src/app.routes.ts";
|
|
343
|
-
if (existsSync(resolve(projectRoot, appRoutes))) return appRoutes;
|
|
344
|
-
return "src/routes.ts";
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
async function closeAndFatal(...msgs) {
|
|
348
|
-
await viteServer.close().catch(() => { });
|
|
349
|
-
fatal(...msgs);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function applyParams(pattern, params) {
|
|
353
|
-
return pattern.replace(/:([\w]+)/g, (_, k) => {
|
|
354
|
-
const v = params[k];
|
|
355
|
-
if (v == null) throw new Error(`[bake] missing param :${k} for ${pattern}`);
|
|
356
|
-
return encodeURIComponent(String(v));
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ---------- Render TemplateResult → HTML string ----------
|
|
361
|
-
//
|
|
362
|
-
// Tiny SSR for TemplateResult. Supports the same shapes as html.ts but
|
|
363
|
-
// without events (@click is stripped) and without live signals (function
|
|
364
|
-
// values are called once).
|
|
365
|
-
|
|
366
|
-
function renderTemplate(tpl, ctx) {
|
|
367
|
-
if (tpl == null || tpl === false || tpl === true) return "";
|
|
368
|
-
if (typeof tpl === "string") return escapeHtml(tpl);
|
|
369
|
-
if (typeof tpl === "number") return String(tpl);
|
|
370
|
-
if (Array.isArray(tpl)) return tpl.map((x) => renderTemplate(x, ctx)).join("");
|
|
371
|
-
if (typeof tpl === "object") {
|
|
372
|
-
if (tpl._mado === true) return renderMadoTemplate(tpl, ctx);
|
|
373
|
-
|
|
374
|
-
// Unknown shapes (e.g. each() directive results) must NOT silently render
|
|
375
|
-
// as "[object Object]". Either each() unwraps to an array here, or we
|
|
376
|
-
// throw with a meaningful location.
|
|
377
|
-
throw new Error(
|
|
378
|
-
`bake cannot render value of type "${tpl._type ?? tpl.constructor?.name ?? "object"}" ` +
|
|
379
|
-
`in route ${ctx?.route ?? "?"}. ` +
|
|
380
|
-
"Hint: each() and other directives are not yet supported in bake. " +
|
|
381
|
-
"Use a plain array (items.map(render)) in baked views, or render this " +
|
|
382
|
-
"section only on the client.",
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
return "";
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function renderMadoTemplate(tpl, ctx) {
|
|
389
|
-
const { strings, values } = tpl;
|
|
390
|
-
let html = "";
|
|
391
|
-
for (let i = 0; i < strings.length; i++) {
|
|
392
|
-
html += strings[i];
|
|
393
|
-
if (i < strings.length - 1) {
|
|
394
|
-
html += renderValue(values[i], inAttributeContext(html), ctx);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
// Strip event markers and normalize property / boolean-attribute forms
|
|
398
|
-
// (mirrors the runtime bindings in src/html/bindings.ts).
|
|
399
|
-
return html
|
|
400
|
-
.replace(/\s+@[\w-]+="[^"]*"/g, "")
|
|
401
|
-
.replace(/\s+\.([\w-]+)="([^"]*)"/g, ' $1="$2"')
|
|
402
|
-
.replace(/\s+\?([\w-]+)="(true|on|1)"/g, ' $1=""')
|
|
403
|
-
.replace(/\s+\?[\w-]+="(false|off|0|)"/g, "");
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function inAttributeContext(html) {
|
|
407
|
-
const lastOpen = html.lastIndexOf("<");
|
|
408
|
-
const lastClose = html.lastIndexOf(">");
|
|
409
|
-
return lastOpen > lastClose;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function renderValue(v, inAttr, ctx) {
|
|
413
|
-
if (v == null || v === false) return "";
|
|
414
|
-
if (v === true) return "";
|
|
415
|
-
if (typeof v === "function") {
|
|
416
|
-
try {
|
|
417
|
-
return renderValue(v(), inAttr, ctx);
|
|
418
|
-
} catch {
|
|
419
|
-
return "";
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
if (Array.isArray(v)) return v.map((x) => renderValue(x, inAttr, ctx)).join("");
|
|
423
|
-
if (v && v._mado === true) return renderMadoTemplate(v, ctx);
|
|
424
|
-
if (v && typeof v === "object" && typeof v._madoDirective === "string") {
|
|
425
|
-
return renderDirective(v, inAttr, ctx);
|
|
426
|
-
}
|
|
427
|
-
if (v && typeof v === "object") {
|
|
428
|
-
// Same defense as renderTemplate(): never silently coerce to "[object Object]".
|
|
429
|
-
throw new Error(
|
|
430
|
-
`bake cannot serialize value of type "${v?._type ?? v?.constructor?.name ?? "object"}" ` +
|
|
431
|
-
`in route ${ctx?.route ?? "?"}. ` +
|
|
432
|
-
"Hint: each() is not yet supported in bake. Use a plain array in baked views.",
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
if (inAttr) return escapeAttr(String(v));
|
|
436
|
-
return escapeHtml(String(v));
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function renderDirective(v, inAttr, ctx) {
|
|
440
|
-
switch (v._madoDirective) {
|
|
441
|
-
case "unsafeHTML": {
|
|
442
|
-
if (inAttr) {
|
|
443
|
-
throw new Error(
|
|
444
|
-
`bake cannot render unsafeHTML() inside an attribute in route ${ctx?.route ?? "?"}.`,
|
|
445
|
-
);
|
|
446
|
-
}
|
|
447
|
-
return String(v.value ?? "");
|
|
448
|
-
}
|
|
449
|
-
case "classMap": {
|
|
450
|
-
const value = Object.entries(v.value ?? {})
|
|
451
|
-
.filter(([, enabled]) => !!enabled)
|
|
452
|
-
.map(([className]) => className)
|
|
453
|
-
.join(" ");
|
|
454
|
-
return inAttr ? escapeAttr(value) : escapeHtml(value);
|
|
455
|
-
}
|
|
456
|
-
case "styleMap": {
|
|
457
|
-
const value = Object.entries(v.value ?? {})
|
|
458
|
-
.filter(([, raw]) => raw != null && raw !== false)
|
|
459
|
-
.map(([name, raw]) => `${toCssPropertyName(name)}:${String(raw)}`)
|
|
460
|
-
.join(";");
|
|
461
|
-
return inAttr ? escapeAttr(value) : escapeHtml(value);
|
|
462
|
-
}
|
|
463
|
-
case "ref":
|
|
464
|
-
return "";
|
|
465
|
-
default:
|
|
466
|
-
throw new Error(
|
|
467
|
-
`bake cannot render directive "${v._madoDirective}" in route ${ctx?.route ?? "?"}.`,
|
|
468
|
-
);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
function toCssPropertyName(name) {
|
|
473
|
-
if (name.startsWith("--")) return name;
|
|
474
|
-
return name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function escapeHtml(s) {
|
|
478
|
-
return s
|
|
479
|
-
.replace(/&/g, "&")
|
|
480
|
-
.replace(/</g, "<")
|
|
481
|
-
.replace(/>/g, ">");
|
|
482
|
-
}
|
|
483
|
-
function escapeAttr(s) {
|
|
484
|
-
return escapeHtml(s).replace(/"/g, """);
|
|
485
|
-
}
|
|
486
|
-
function escapeXml(s) {
|
|
487
|
-
return s
|
|
488
|
-
.replace(/&/g, "&")
|
|
489
|
-
.replace(/</g, "<")
|
|
490
|
-
.replace(/>/g, ">")
|
|
491
|
-
.replace(/"/g, """);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// ---------- Final HTML with head + baked data ----------
|
|
495
|
-
|
|
496
|
-
function buildHtml({ template, bodyHtml, head, bakedData, revalidate, canonical }) {
|
|
497
|
-
const { document } = parseHTML(template);
|
|
498
|
-
|
|
499
|
-
if (head.title) document.title = head.title;
|
|
500
|
-
if (head.description) {
|
|
501
|
-
setMeta(document, { name: "description", content: head.description });
|
|
502
|
-
}
|
|
503
|
-
if (canonical) {
|
|
504
|
-
setLink(document, { rel: "canonical", href: canonical });
|
|
505
|
-
}
|
|
506
|
-
if (head.og) {
|
|
507
|
-
for (const [k, v] of Object.entries(head.og)) {
|
|
508
|
-
if (!v) continue;
|
|
509
|
-
setMeta(document, { property: `og:${k}`, content: String(v) });
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
if (head.twitter || head.og) {
|
|
513
|
-
const tw = head.twitter ?? {};
|
|
514
|
-
const og = head.og ?? {};
|
|
515
|
-
setMeta(document, { name: "twitter:card", content: tw.card ?? "summary" });
|
|
516
|
-
if (tw.title ?? og.title)
|
|
517
|
-
setMeta(document, { name: "twitter:title", content: tw.title ?? og.title });
|
|
518
|
-
if (tw.description ?? og.description)
|
|
519
|
-
setMeta(document, { name: "twitter:description", content: tw.description ?? og.description });
|
|
520
|
-
if (tw.image ?? og.image)
|
|
521
|
-
setMeta(document, { name: "twitter:image", content: tw.image ?? og.image });
|
|
522
|
-
}
|
|
523
|
-
for (const m of head.meta ?? []) setMeta(document, m);
|
|
524
|
-
for (const l of head.link ?? []) setLink(document, l);
|
|
525
|
-
|
|
526
|
-
if (head.jsonLd != null) {
|
|
527
|
-
const s = document.createElement("script");
|
|
528
|
-
s.setAttribute("type", "application/ld+json");
|
|
529
|
-
s.setAttribute("data-mado-head", "baked");
|
|
530
|
-
s.textContent = JSON.stringify(head.jsonLd);
|
|
531
|
-
document.head.appendChild(s);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (revalidate) {
|
|
535
|
-
setMeta(document, { name: "bake-revalidate", content: String(revalidate) });
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
if (bakedData !== undefined) {
|
|
539
|
-
const s = document.createElement("script");
|
|
540
|
-
s.setAttribute("type", "application/json");
|
|
541
|
-
s.id = "bake";
|
|
542
|
-
s.textContent = JSON.stringify(bakedData);
|
|
543
|
-
document.body.appendChild(s);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
const app = document.getElementById("app");
|
|
547
|
-
if (app) {
|
|
548
|
-
app.setAttribute("data-mado-baked", "");
|
|
549
|
-
app.innerHTML = bodyHtml;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
return "<!doctype html>\n" + document.documentElement.outerHTML;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function setMeta(doc, attrs) {
|
|
556
|
-
const m = doc.createElement("meta");
|
|
557
|
-
if (attrs.name) m.setAttribute("name", attrs.name);
|
|
558
|
-
if (attrs.property) m.setAttribute("property", attrs.property);
|
|
559
|
-
m.setAttribute("content", attrs.content);
|
|
560
|
-
m.setAttribute("data-mado-head", "baked");
|
|
561
|
-
doc.head.appendChild(m);
|
|
562
|
-
}
|
|
563
|
-
function setLink(doc, attrs) {
|
|
564
|
-
const l = doc.createElement("link");
|
|
565
|
-
l.setAttribute("rel", attrs.rel);
|
|
566
|
-
l.setAttribute("href", attrs.href);
|
|
567
|
-
if (attrs.hreflang) l.setAttribute("hreflang", attrs.hreflang);
|
|
568
|
-
l.setAttribute("data-mado-head", "baked");
|
|
569
|
-
doc.head.appendChild(l);
|
|
570
|
-
}
|
|
@@ -1,77 +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
|
-
await run(
|
|
25
|
-
process.execPath,
|
|
26
|
-
[
|
|
27
|
-
"--input-type=module",
|
|
28
|
-
"--eval",
|
|
29
|
-
`
|
|
30
|
-
import { html, signal } from "@madojs/mado";
|
|
31
|
-
import "@madojs/mado/devtools.js";
|
|
32
|
-
import { mado } from "@madojs/mado/vite";
|
|
33
|
-
if (typeof html !== "function" || typeof signal !== "function") {
|
|
34
|
-
throw new Error("public root import failed");
|
|
35
|
-
}
|
|
36
|
-
if (typeof mado !== "function") throw new Error("vite plugin import failed");
|
|
37
|
-
try {
|
|
38
|
-
await import("@madojs/mado/lifecycle.js");
|
|
39
|
-
throw new Error("internal lifecycle subpath unexpectedly resolved");
|
|
40
|
-
} catch (err) {
|
|
41
|
-
if (err?.code !== "ERR_PACKAGE_PATH_NOT_EXPORTED") throw err;
|
|
42
|
-
}
|
|
43
|
-
`,
|
|
44
|
-
],
|
|
45
|
-
{ cwd: installRoot },
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
await run("npx", ["mado", "init", "smoke-app"], {
|
|
49
|
-
cwd: installRoot,
|
|
50
|
-
env: { ...process.env, MADO_PACKAGE_SPEC: tarball },
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const appRoot = join(installRoot, "smoke-app");
|
|
54
|
-
await run("npm", ["install"], { cwd: appRoot });
|
|
55
|
-
await run("npm", ["run", "new", "--", "module", "smoke"], { cwd: appRoot });
|
|
56
|
-
await run("npm", ["run", "release"], { cwd: appRoot });
|
|
57
|
-
|
|
58
|
-
console.log(`[package-smoke] ok ${basename(tarball)}`);
|
|
59
|
-
} finally {
|
|
60
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
61
|
-
if (tarball) await rm(tarball, { force: true });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function run(cmd, args, options) {
|
|
65
|
-
console.log(`[package-smoke] ${cmd} ${args.join(" ")}`);
|
|
66
|
-
try {
|
|
67
|
-
await exec(cmd, args, {
|
|
68
|
-
cwd: options.cwd,
|
|
69
|
-
env: options.env ?? process.env,
|
|
70
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
71
|
-
});
|
|
72
|
-
} catch (err) {
|
|
73
|
-
if (err.stdout) process.stdout.write(err.stdout);
|
|
74
|
-
if (err.stderr) process.stderr.write(err.stderr);
|
|
75
|
-
throw err;
|
|
76
|
-
}
|
|
77
|
-
}
|