generator-white-label 10.0.0 → 10.0.3
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/PACKAGE_MANAGERS.md +1 -1
- package/README.md +4 -4
- package/dist/scaffold/index.js +6 -6
- package/dist/scaffold/index.js.map +1 -1
- package/dist/scripts/build.js +23 -5
- package/dist/scripts/build.js.map +1 -1
- package/dist/server/handler.js +1 -1
- package/dist/server/handler.js.map +1 -1
- package/package.json +5 -5
- package/scaffold/AGENTS.md +1 -1
- package/scaffold/index.ts +6 -6
- package/scripts/build.ts +19 -5
- package/server/handler.ts +1 -1
package/PACKAGE_MANAGERS.md
CHANGED
|
@@ -34,4 +34,4 @@ Yarn's package-age security gate is left enabled for ordinary dependencies. The
|
|
|
34
34
|
|
|
35
35
|
The committed `package-lock.json` remains the generator repository's canonical dependency lockfile and npm remains the maintenance/audit path used by primary CI. Compatibility CI packs the real generator artifact and verifies its API and CLI under npm, Yarn, and pnpm. Alternate lockfiles are not committed merely for compatibility testing.
|
|
36
36
|
|
|
37
|
-
Generator 10
|
|
37
|
+
Generator 10 pins the published runtime line exactly, including `white-label-view@7.0.0`, and the committed lockfile resolves those dependencies from the npm registry. The security workflow also substitutes a fixed packed View 7 source revision in coordinated integration jobs; that is an additional cross-repository compatibility check, not a workaround for an unpublished View release. Keep the release lockfile registry-based rather than replacing runtime dependencies with Git or local package references.
|
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ const input = html`
|
|
|
90
90
|
|
|
91
91
|
The tagged-template runtime rejects interpolation in ambiguous or dangerous contexts such as script/style bodies, comments, tag names, and unquoted attribute positions rather than pretending generic escaping makes those contexts safe.
|
|
92
92
|
|
|
93
|
-
White Label View remains template-engine agnostic.
|
|
93
|
+
White Label View remains template-engine agnostic. Handlebars, Eta, EJS, Mustache, Nunjucks, Pug, KitaJS HTML, and other compatible renderers can remain application dependencies and return their rendered output through View's normal `template` contract.
|
|
94
94
|
|
|
95
95
|
See [Template engines](https://whitelabeljs.org/docs/view/#template-engines) for tested integrations and trust boundaries.
|
|
96
96
|
|
|
@@ -154,7 +154,7 @@ npm install && npm test
|
|
|
154
154
|
# or: pnpm install && pnpm test
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
There is one canonical scaffold. The CLI has no renderer prompt
|
|
157
|
+
There is one canonical scaffold. The CLI has no renderer prompt or renderer-specific mode switch.
|
|
158
158
|
|
|
159
159
|
The generator refuses to layer a scaffold over an existing non-empty destination. This protection is enforced by the shared `createProject()` engine for both CLI and programmatic use. An existing empty directory is allowed; a missing directory is created.
|
|
160
160
|
|
|
@@ -239,7 +239,7 @@ The Web-target smoke test does **not** claim blanket Cloudflare/Deno/edge-provid
|
|
|
239
239
|
| `test/` | Executable contracts and integration tests |
|
|
240
240
|
| `template-test/` | Generated-project validation |
|
|
241
241
|
|
|
242
|
-
No React, Bootstrap, Sass, Eta, Handlebars, Mustache, Nunjucks, Pug, web font, cloud SDK, or browser-side template framework is required. Optional renderers/providers remain application dependencies.
|
|
242
|
+
No React, Bootstrap, Sass, Eta, Handlebars, Mustache, Nunjucks, Pug, KitaJS HTML, web font, cloud SDK, or browser-side template framework is required. Optional renderers/providers remain application dependencies.
|
|
243
243
|
|
|
244
244
|
## Build and verify
|
|
245
245
|
|
|
@@ -273,7 +273,7 @@ Tests are part of the documentation. Executable project source is held to 100% s
|
|
|
273
273
|
|
|
274
274
|
## Coordinated runtime release
|
|
275
275
|
|
|
276
|
-
Generator 10 targets the published White Label runtime line: `white-label-mediator@5.0.
|
|
276
|
+
Generator 10 targets the published White Label runtime line: `white-label-mediator@5.0.1`, `white-label-model@7.0.3`, `white-label-router@6.1.2`, and `white-label-view@7.0.2`. The release and install baseline is registry-backed; CI additionally substitutes a fixed packed View 7 source revision in coordinated integration jobs.
|
|
277
277
|
|
|
278
278
|
## White Label ecosystem
|
|
279
279
|
|
package/dist/scaffold/index.js
CHANGED
|
@@ -6,11 +6,11 @@ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '
|
|
|
6
6
|
const nodeFileSystem = {
|
|
7
7
|
async copy(source, destination) {
|
|
8
8
|
await mkdir(path.dirname(destination), { recursive: true });
|
|
9
|
-
await cp(source, destination, { recursive: true });
|
|
9
|
+
await cp(source, destination, { recursive: true, force: false, errorOnExist: true });
|
|
10
10
|
},
|
|
11
11
|
async writeJSON(destination, value) {
|
|
12
12
|
await mkdir(path.dirname(destination), { recursive: true });
|
|
13
|
-
await writeFile(destination, `${JSON.stringify(value, null, 2)}\n
|
|
13
|
+
await writeFile(destination, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx' });
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
/** Refuse to layer a generated project over existing user files. */
|
|
@@ -60,10 +60,10 @@ export function createSiteManifest() {
|
|
|
60
60
|
'typescript': '7.0.2'
|
|
61
61
|
},
|
|
62
62
|
dependencies: {
|
|
63
|
-
'white-label-mediator': '5.0.
|
|
64
|
-
'white-label-model': '7.0.
|
|
65
|
-
'white-label-router': '6.1.
|
|
66
|
-
'white-label-view': '7.0.
|
|
63
|
+
'white-label-mediator': '5.0.1',
|
|
64
|
+
'white-label-model': '7.0.3',
|
|
65
|
+
'white-label-router': '6.1.2',
|
|
66
|
+
'white-label-view': '7.0.2'
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../scaffold/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAC/D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAYxF,MAAM,cAAc,GAAuB;IACvC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW;QAC1B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../scaffold/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAC/D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAYxF,MAAM,cAAc,GAAuB;IACvC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW;QAC1B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAC,CAAC,CAAC;IACvF,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK;QAC9B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IACtF,CAAC;CACJ,CAAC;AAEF,oEAAoE;AACpE,KAAK,UAAU,0BAA0B,CAAC,WAAmB;IACzD,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAAA,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,EAAE,CAAC,CAAC;QAAA,CAAC;IACjG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAAA,OAAO;QAAA,CAAC;QACnF,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB;IAC9B,OAAO;QACH,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAC,IAAI,EAAE,uBAAuB,EAAC;QACxC,OAAO,EAAE;YACL,KAAK,EAAE,oDAAoD;YAC3D,SAAS,EAAE,+BAA+B;YAC1C,IAAI,EAAE,qTAAqT;SAC9T;QACD,YAAY,EAAE;YACV,uBAAuB,EAAE,IAAI;YAC7B,gBAAgB,EAAE,IAAI;SACzB;QACD,gBAAgB,EAAE;YACd,uBAAuB,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC;YACtC,gBAAgB,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC;SAClC;QACD,eAAe,EAAE;YACb,kBAAkB,EAAE,OAAO;YAC3B,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,QAAQ;YACnB,eAAe,EAAE,SAAS;YAC1B,OAAO,EAAE,QAAQ;YACjB,aAAa,EAAE,OAAO;YACtB,YAAY,EAAE,OAAO;SACxB;QACD,YAAY,EAAE;YACV,sBAAsB,EAAE,OAAO;YAC/B,mBAAmB,EAAE,OAAO;YAC5B,oBAAoB,EAAE,OAAO;YAC7B,kBAAkB,EAAE,OAAO;SAC9B;KACJ,CAAC;AACN,CAAC;AAED,MAAM,cAAc,GAAG;IACnB,CAAC,eAAe,EAAE,eAAe,CAAC;IAClC,CAAC,aAAa,EAAE,aAAa,CAAC;IAC9B,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;IAC9C,CAAC,KAAK,EAAE,KAAK,CAAC;IACd,CAAC,eAAe,EAAE,WAAW,CAAC;IAC9B,CAAC,QAAQ,EAAE,QAAQ,CAAC;IACpB,CAAC,SAAS,EAAE,SAAS,CAAC;IACtB,CAAC,eAAe,EAAE,MAAM,CAAC;IACzB,CAAC,oBAAoB,EAAE,eAAe,CAAC;CACjC,CAAC;AAEX,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAC,WAAW,EAAE,UAAU,GAAG,cAAc,EAAuB;IAChG,MAAM,0BAA0B,CAAC,WAAW,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC5C,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,MAAM,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["/** @module scaffold */\nimport {cp, mkdir, readdir, writeFile} from 'node:fs/promises';\nimport path from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');\n\nexport interface ScaffoldFileSystem {\n copy(source: string, destination: string): void | Promise<void>;\n writeJSON(destination: string, value: unknown): void | Promise<void>;\n}\n\nexport interface CreateProjectOptions {\n destination: string;\n fileSystem?: ScaffoldFileSystem;\n}\n\nconst nodeFileSystem: ScaffoldFileSystem = {\n async copy(source, destination) {\n await mkdir(path.dirname(destination), {recursive: true});\n await cp(source, destination, {recursive: true, force: false, errorOnExist: true});\n },\n async writeJSON(destination, value) {\n await mkdir(path.dirname(destination), {recursive: true});\n await writeFile(destination, `${JSON.stringify(value, null, 2)}\\n`, {flag: 'wx'});\n }\n};\n\n/** Refuse to layer a generated project over existing user files. */\nasync function assertDestinationAvailable(destination: string) {\n try {\n const entries = await readdir(destination);\n if (entries.length) {throw new Error(`Destination directory must be empty: ${destination}`);}\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {return;}\n throw error;\n }\n}\n\n/** Return the package manifest used by generated White Label projects. */\nexport function createSiteManifest() {\n return {\n name: 'white-label-site',\n version: '1.0.0',\n private: true,\n type: 'module',\n engines: {node: '^22.18.0 || >=24.11.0'},\n scripts: {\n build: 'tsc -p tsconfig.json && node dist/scripts/build.js',\n typecheck: 'tsc -p tsconfig.json --noEmit',\n test: 'node --run typecheck && node --run build -- --version=test --production=true --site-url=https://example.com && node --test --experimental-test-coverage --test-coverage-include=dist/app/assets/script/index.js --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 test/*.test.js'\n },\n allowScripts: {\n '@parcel/watcher@2.5.1': true,\n 'esbuild@0.28.2': true\n },\n dependenciesMeta: {\n '@parcel/watcher@2.5.1': {built: true},\n 'esbuild@0.28.2': {built: true}\n },\n devDependencies: {\n '@tailwindcss/cli': '4.3.3',\n '@types/node': '24.13.3',\n 'axe-core': '4.13.0',\n 'esbuild': '0.28.2',\n 'html-validate': '11.15.0',\n 'jsdom': '30.0.1',\n 'tailwindcss': '4.3.3',\n 'typescript': '7.0.2'\n },\n dependencies: {\n 'white-label-mediator': '5.0.1',\n 'white-label-model': '7.0.3',\n 'white-label-router': '6.1.2',\n 'white-label-view': '7.0.2'\n }\n };\n}\n\nconst scaffoldCopies = [\n ['.editorconfig', '.editorconfig'],\n ['.yarnrc.yml', '.yarnrc.yml'],\n ['pnpm-workspace.yaml', 'pnpm-workspace.yaml'],\n ['app', 'app'],\n ['app/README.md', 'README.md'],\n ['server', 'server'],\n ['scripts', 'scripts'],\n ['template-test', 'test'],\n ['tsconfig.site.json', 'tsconfig.json']\n] as const;\n\n/** Create the canonical tagged-template White Label starter without overwriting user files. */\nexport async function createProject({destination, fileSystem = nodeFileSystem}: CreateProjectOptions) {\n await assertDestinationAvailable(destination);\n for (const [source, target] of scaffoldCopies) {\n await fileSystem.copy(path.join(packageRoot, source), path.join(destination, target));\n }\n await fileSystem.writeJSON(path.join(destination, 'package.json'), createSiteManifest());\n}\n"]}
|
package/dist/scripts/build.js
CHANGED
|
@@ -7,6 +7,7 @@ import { build as buildJavaScript } from 'esbuild';
|
|
|
7
7
|
const execFileAsync = promisify(execFile);
|
|
8
8
|
const defaultProjectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
9
9
|
const relativePublicPrefix = /^\/(?!\/)[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/;
|
|
10
|
+
const buildOptionNames = new Set(['cdn', 'production', 'site-url', 'version', 'www']);
|
|
10
11
|
function hasControlCharacters(value) {
|
|
11
12
|
return [...value].some(character => {
|
|
12
13
|
const code = character.charCodeAt(0);
|
|
@@ -75,11 +76,28 @@ function normalizeBuildConfig(config) {
|
|
|
75
76
|
}
|
|
76
77
|
/** Read deployment flags and reject unsafe or invalid deployment values. */
|
|
77
78
|
export function parseArguments(argumentsList) {
|
|
78
|
-
const values =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
const values = {};
|
|
80
|
+
for (const argument of argumentsList) {
|
|
81
|
+
if (!argument.startsWith('--')) {
|
|
82
|
+
throw new Error(`Unknown build option: ${argument}`);
|
|
83
|
+
}
|
|
84
|
+
const separator = argument.indexOf('=');
|
|
85
|
+
const key = argument.slice(2, separator === -1 ? undefined : separator);
|
|
86
|
+
if (!buildOptionNames.has(key)) {
|
|
87
|
+
throw new Error(`Unknown build option: --${key}`);
|
|
88
|
+
}
|
|
89
|
+
if (separator === -1) {
|
|
90
|
+
throw new Error(`Build option --${key} must use --${key}=value`);
|
|
91
|
+
}
|
|
92
|
+
values[key] = argument.slice(separator + 1);
|
|
93
|
+
}
|
|
94
|
+
let production = false;
|
|
95
|
+
if (values.production !== undefined) {
|
|
96
|
+
if (values.production !== 'true' && values.production !== 'false') {
|
|
97
|
+
throw new Error('Production must be true or false');
|
|
98
|
+
}
|
|
99
|
+
production = values.production === 'true';
|
|
100
|
+
}
|
|
83
101
|
return normalizeBuildConfig({
|
|
84
102
|
cdn: values.cdn || '/',
|
|
85
103
|
production,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../scripts/build.ts"],"names":[],"mappings":"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","sourcesContent":["/** Values injected into page templates and the generated config file. */\nexport interface BuildConfig {cdn: string; production: boolean; siteUrl: string; version: string; www: string}\nimport {execFile} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {promisify} from 'node:util';\nimport {fileURLToPath, pathToFileURL} from 'node:url';\nimport {build as buildJavaScript} from 'esbuild';\n\nconst execFileAsync = promisify(execFile);\nconst defaultProjectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');\nconst relativePublicPrefix = /^\\/(?!\\/)[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/;\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some(character => {\n const code = character.charCodeAt(0);\n return code <= 0x1f || code === 0x7f;\n });\n}\n\nfunction normalizeVersion(value: unknown): string {\n if (typeof value !== 'string' || !/^[A-Za-z0-9._-]+$/.test(value) || value === '.' || value === '..') {\n throw new Error('Version may contain only letters, numbers, dots, underscores, and hyphens and must name one release directory');\n }\n return value;\n}\n\nfunction normalizeProduction(value: unknown): boolean {\n if (typeof value !== 'boolean') {throw new Error('Production must be a boolean');}\n return value;\n}\n\nfunction normalizeSiteUrl(value: unknown, production: boolean): string {\n if (typeof value !== 'string') {\n throw new Error('Site URL must be an absolute HTTP(S) URL; production builds require HTTPS');\n }\n let url: URL;\n try {url = new URL(value);} catch {throw new Error('Site URL must be an absolute HTTP(S) URL; production builds require HTTPS');}\n if (hasControlCharacters(value) || (url.protocol !== 'http:' && url.protocol !== 'https:') ||\n url.username || url.password || url.search || url.hash || (production && url.protocol !== 'https:')) {\n throw new Error('Site URL must be an absolute HTTP(S) URL without credentials, query, or fragment; production builds require HTTPS');\n }\n return url.toString().replace(/\\/$/, '');\n}\n\nfunction normalizePublicPrefix(value: unknown, name: 'www' | 'cdn', production: boolean): string {\n if (typeof value !== 'string' || hasControlCharacters(value)) {\n throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix`);\n }\n if (relativePublicPrefix.test(value)) {return value.endsWith('/') ? value : `${value}/`;}\n let url: URL;\n try {url = new URL(value);} catch {throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix`);}\n if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password ||\n url.search || url.hash || (production && url.protocol !== 'https:')) {\n throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix${production ? ' using HTTPS in production' : ''}`);\n }\n const normalized = url.toString();\n return normalized.endsWith('/') ? normalized : `${normalized}/`;\n}\n\nfunction normalizeBuildConfig(config: BuildConfig): BuildConfig {\n const production = normalizeProduction(config.production);\n return {\n cdn: normalizePublicPrefix(config.cdn, 'cdn', production),\n production,\n siteUrl: normalizeSiteUrl(config.siteUrl, production),\n version: normalizeVersion(config.version),\n www: normalizePublicPrefix(config.www, 'www', production)\n };\n}\n\n/** Read deployment flags and reject unsafe or invalid deployment values. */\nexport function parseArguments(argumentsList: string[]): BuildConfig {\n const values = Object.fromEntries(argumentsList.map((argument) => {\n const [key, ...value] = argument.replace(/^--/, '').split('=');\n return [key, value.join('=')];\n }));\n const production = values.production === 'true';\n return normalizeBuildConfig({\n cdn: values.cdn || '/',\n production,\n siteUrl: values['site-url'] || 'http://localhost:8080',\n version: values.version || String(Math.floor(Date.now() / 1000)),\n www: values.www || '/'\n });\n}\n\n/** Return the local Tailwind executable name for the current platform. */\nexport function tailwindExecutable(platform: NodeJS.Platform = process.platform) {\n return platform === 'win32' ? 'tailwindcss.cmd' : 'tailwindcss';\n}\n\n/** Recursively collect files below a directory, propagating filesystem failures. */\nasync function filesUnder(directory: string): Promise<string[]> {\n const entries = await fs.readdir(directory, {withFileTypes: true});\n const files = await Promise.all(entries.map(async (entry) => {\n const location = path.join(directory, entry.name);\n return entry.isDirectory() ? filesUnder(location) : [location];\n }));\n return files.flat();\n}\n\ninterface PageModule {\n default(data: Record<string, unknown>): {toString(): string} | string;\n}\n\n/** Render compiled TypeScript pages using global, page-specific, and deployment data. */\nasync function renderMarkup(config: BuildConfig, outputRoot: string, projectRoot: string) {\n const globalData = JSON.parse(await fs.readFile(\n path.join(projectRoot, 'app/assets/data/view/global.json'), 'utf8'\n )) as Record<string, unknown>;\n const appRoot = path.join(projectRoot, 'app');\n const pages = (await filesUnder(appRoot))\n .filter((file) => /\\.ts$/.test(file) && !file.endsWith('.d.ts') && !file.includes(`${path.sep}assets${path.sep}`));\n\n await Promise.all(pages.map(async (page) => {\n const relative = path.relative(appRoot, page);\n const pageDataPath = path.join(projectRoot, 'app/assets/data/view', relative.replace(/\\.ts$/, '.json'));\n let pageData: Record<string, unknown> = {};\n try {\n pageData = JSON.parse(await fs.readFile(pageDataPath, 'utf8')) as Record<string, unknown>;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {\n throw error;\n }\n }\n const compiledPage = path.join(projectRoot, 'dist/app', relative.replace(/\\.ts$/, '.js'));\n const module = await import(pathToFileURL(compiledPage).href) as PageModule;\n if (typeof module.default !== 'function') {\n throw new TypeError(`Page module ${relative} must export a default render function`);\n }\n const markup = module.default({...globalData, ...pageData, ...config});\n const destination = path.join(outputRoot, relative.replace(/\\.ts$/, '.html'));\n await fs.mkdir(path.dirname(destination), {recursive: true});\n await fs.writeFile(destination, `<!DOCTYPE html>\\n${String(markup)}\\n`);\n }));\n}\n\n/** Compile Tailwind and project CSS into the deploy directory. */\nasync function compileStyles(outputAssets: string, production: boolean, projectRoot: string) {\n const styleRoot = path.join(projectRoot, 'app/assets/style');\n await fs.mkdir(path.join(outputAssets, 'style'), {recursive: true});\n const destination = path.join(outputAssets, 'style/global.css');\n const argumentsList = [\n '-i', path.join(styleRoot, 'global.css'),\n '-o', destination\n ];\n if (production) {argumentsList.push('--minify');}\n await execFileAsync(tailwindExecutable(), argumentsList, {cwd: projectRoot});\n await fs.copyFile(path.join(styleRoot, 'print.css'), path.join(outputAssets, 'style/print.css'));\n}\n\n/** Bundle plain TypeScript browser entry points, excluding declaration-only files. */\nasync function compileScripts(outputAssets: string, production: boolean, projectRoot: string) {\n const scriptRoot = path.join(projectRoot, 'app/assets/script');\n const entries = (await fs.readdir(scriptRoot, {withFileTypes: true}))\n .filter((entry) => entry.isFile() && !entry.name.endsWith('.d.ts') && entry.name.endsWith('.ts'))\n .map((entry) => path.join(scriptRoot, entry.name));\n await fs.mkdir(path.join(outputAssets, 'script'), {recursive: true});\n await buildJavaScript({\n bundle: true,\n entryNames: '[name].compiled',\n entryPoints: entries,\n format: 'iife',\n loader: {'.ts': 'ts'},\n minify: production,\n outdir: path.join(outputAssets, 'script'),\n sourcemap: !production,\n target: ['es2018']\n });\n await fs.writeFile(path.join(outputAssets, 'script/global.compiled.js'), '');\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\n\n/** Replace the deployment directory with compiled pages, scripts, styles, and static assets. */\nexport async function build(config = parseArguments(process.argv.slice(2)), projectRoot = defaultProjectRoot) {\n const safeConfig = normalizeBuildConfig(config);\n const outputRoot = path.join(projectRoot, '_deploy');\n const outputAssets = path.join(outputRoot, 'release', safeConfig.version, 'assets');\n await fs.rm(outputRoot, {recursive: true, force: true});\n await fs.mkdir(outputAssets, {recursive: true});\n\n await fs.cp(path.join(projectRoot, 'app/assets/data'), path.join(outputAssets, 'data'), {recursive: true});\n await fs.writeFile(path.join(outputAssets, 'data/config.json'), JSON.stringify(safeConfig));\n await renderMarkup(safeConfig, outputRoot, projectRoot);\n await compileStyles(outputAssets, safeConfig.production, projectRoot);\n await compileScripts(outputAssets, safeConfig.production, projectRoot);\n const robots = `User-agent: *\\nAllow: /\\nSitemap: ${safeConfig.siteUrl}/sitemap.xml\\n`;\n await fs.writeFile(path.join(outputRoot, 'robots.txt'), robots);\n const sitemap = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"><url><loc>${escapeXml(`${safeConfig.siteUrl}/`)}</loc></url></urlset>\\n`;\n await fs.writeFile(path.join(outputRoot, 'sitemap.xml'), sitemap);\n}\n\nif (path.resolve(process.argv[1] || '') === fileURLToPath(import.meta.url)) {\n await build();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../scripts/build.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAAC,aAAa,EAAE,aAAa,EAAC,MAAM,UAAU,CAAC;AACtD,OAAO,EAAC,KAAK,IAAI,eAAe,EAAC,MAAM,SAAS,CAAC;AAEjD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC1C,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC/F,MAAM,oBAAoB,GAAG,2CAA2C,CAAC;AACzE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AAEtF,SAAS,oBAAoB,CAAC,KAAa;IACvC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnG,MAAM,IAAI,KAAK,CAAC,+GAA+G,CAAC,CAAC;IACrI,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAAA,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAAA,CAAC;IAClF,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc,EAAE,UAAmB;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QAAA,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAAA,CAAC;IAAC,MAAM,CAAC;QAAA,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAAA,CAAC;IACjI,IAAI,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACtF,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;QACtG,MAAM,IAAI,KAAK,CAAC,mHAAmH,CAAC,CAAC;IACzI,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc,EAAE,IAAmB,EAAE,UAAmB;IACnF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yDAAyD,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAAA,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;IAAA,CAAC;IACzF,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QAAA,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAAA,CAAC;IAAC,MAAM,CAAC;QAAA,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yDAAyD,CAAC,CAAC;IAAA,CAAC;IACtH,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QACvF,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,0DAA0D,UAAU,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvI,CAAC;IACD,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC;AACpE,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAmB;IAC7C,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1D,OAAO;QACH,GAAG,EAAE,qBAAqB,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC;QACzD,UAAU;QACV,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;QACrD,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC;QACzC,GAAG,EAAE,qBAAqB,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC;KAC5D,CAAC;AACN,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,aAAuB;IAClD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;QAAA,CAAC;QACvF,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACxE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;QAAA,CAAC;QACpF,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YAAA,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,eAAe,GAAG,QAAQ,CAAC,CAAC;QAAA,CAAC;QACzF,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACxD,CAAC;QACD,UAAU,GAAG,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC;IAC9C,CAAC;IAED,OAAO,oBAAoB,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG;QACtB,UAAU;QACV,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,uBAAuB;QACtD,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAChE,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG;KACzB,CAAC,CAAC;AACP,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,QAAQ,GAAoB,OAAO,CAAC,QAAQ;IAC3E,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,CAAC;AACpE,CAAC;AAED,oFAAoF;AACpF,KAAK,UAAU,UAAU,CAAC,SAAiB;IACvC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC,CAAC;IACJ,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAMD,yFAAyF;AACzF,KAAK,UAAU,YAAY,CAAC,MAAmB,EAAE,UAAkB,EAAE,WAAmB;IACpF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC3C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kCAAkC,CAAC,EAAE,MAAM,CACrE,CAA4B,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;SACpC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAEvH,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACxG,IAAI,QAAQ,GAA4B,EAAE,CAAC;QAC3C,IAAI,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAA4B,CAAC;QAC9F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC1E,MAAM,KAAK,CAAC;YAChB,CAAC;QACL,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1F,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,IAAI,CAAe,CAAC;QAC5E,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,SAAS,CAAC,eAAe,QAAQ,wCAAwC,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAC,GAAG,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAC,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9E,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,oBAAoB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED,kEAAkE;AAClE,KAAK,UAAU,aAAa,CAAC,YAAoB,EAAE,UAAmB,EAAE,WAAmB;IACvF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG;QAClB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;QACxC,IAAI,EAAE,WAAW;KACpB,CAAC;IACF,IAAI,UAAU,EAAE,CAAC;QAAA,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAAA,CAAC;IACjD,MAAM,aAAa,CAAC,kBAAkB,EAAE,EAAE,aAAa,EAAE,EAAC,GAAG,EAAE,WAAW,EAAC,CAAC,CAAC;IAC7E,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC;AACrG,CAAC;AAED,sFAAsF;AACtF,KAAK,UAAU,cAAc,CAAC,YAAoB,EAAE,UAAmB,EAAE,WAAmB;IACxF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;SAChE,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IACrE,MAAM,eAAe,CAAC;QAClB,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,iBAAiB;QAC7B,WAAW,EAAE,OAAO;QACpB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC;QACrB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC;QACzC,SAAS,EAAE,CAAC,UAAU;QACtB,MAAM,EAAE,CAAC,QAAQ,CAAC;KACrB,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,2BAA2B,CAAC,EAAE,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC5B,OAAO,KAAK;SACP,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,GAAG,kBAAkB;IACxG,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACpF,MAAM,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IACxD,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAEhD,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAC3G,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5F,MAAM,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACxD,MAAM,aAAa,CAAC,YAAY,EAAE,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACtE,MAAM,cAAc,CAAC,YAAY,EAAE,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,qCAAqC,UAAU,CAAC,OAAO,gBAAgB,CAAC;IACvF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,iHAAiH,SAAS,CAAC,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,yBAAyB,CAAC;IAC9L,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACzE,MAAM,KAAK,EAAE,CAAC;AAClB,CAAC","sourcesContent":["/** Values injected into page templates and the generated config file. */\nexport interface BuildConfig {cdn: string; production: boolean; siteUrl: string; version: string; www: string}\nimport {execFile} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {promisify} from 'node:util';\nimport {fileURLToPath, pathToFileURL} from 'node:url';\nimport {build as buildJavaScript} from 'esbuild';\n\nconst execFileAsync = promisify(execFile);\nconst defaultProjectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');\nconst relativePublicPrefix = /^\\/(?!\\/)[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/;\nconst buildOptionNames = new Set(['cdn', 'production', 'site-url', 'version', 'www']);\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some(character => {\n const code = character.charCodeAt(0);\n return code <= 0x1f || code === 0x7f;\n });\n}\n\nfunction normalizeVersion(value: unknown): string {\n if (typeof value !== 'string' || !/^[A-Za-z0-9._-]+$/.test(value) || value === '.' || value === '..') {\n throw new Error('Version may contain only letters, numbers, dots, underscores, and hyphens and must name one release directory');\n }\n return value;\n}\n\nfunction normalizeProduction(value: unknown): boolean {\n if (typeof value !== 'boolean') {throw new Error('Production must be a boolean');}\n return value;\n}\n\nfunction normalizeSiteUrl(value: unknown, production: boolean): string {\n if (typeof value !== 'string') {\n throw new Error('Site URL must be an absolute HTTP(S) URL; production builds require HTTPS');\n }\n let url: URL;\n try {url = new URL(value);} catch {throw new Error('Site URL must be an absolute HTTP(S) URL; production builds require HTTPS');}\n if (hasControlCharacters(value) || (url.protocol !== 'http:' && url.protocol !== 'https:') ||\n url.username || url.password || url.search || url.hash || (production && url.protocol !== 'https:')) {\n throw new Error('Site URL must be an absolute HTTP(S) URL without credentials, query, or fragment; production builds require HTTPS');\n }\n return url.toString().replace(/\\/$/, '');\n}\n\nfunction normalizePublicPrefix(value: unknown, name: 'www' | 'cdn', production: boolean): string {\n if (typeof value !== 'string' || hasControlCharacters(value)) {\n throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix`);\n }\n if (relativePublicPrefix.test(value)) {return value.endsWith('/') ? value : `${value}/`;}\n let url: URL;\n try {url = new URL(value);} catch {throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix`);}\n if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password ||\n url.search || url.hash || (production && url.protocol !== 'https:')) {\n throw new Error(`${name} must be a root-relative or absolute HTTP(S) URL prefix${production ? ' using HTTPS in production' : ''}`);\n }\n const normalized = url.toString();\n return normalized.endsWith('/') ? normalized : `${normalized}/`;\n}\n\nfunction normalizeBuildConfig(config: BuildConfig): BuildConfig {\n const production = normalizeProduction(config.production);\n return {\n cdn: normalizePublicPrefix(config.cdn, 'cdn', production),\n production,\n siteUrl: normalizeSiteUrl(config.siteUrl, production),\n version: normalizeVersion(config.version),\n www: normalizePublicPrefix(config.www, 'www', production)\n };\n}\n\n/** Read deployment flags and reject unsafe or invalid deployment values. */\nexport function parseArguments(argumentsList: string[]): BuildConfig {\n const values: Record<string, string> = {};\n for (const argument of argumentsList) {\n if (!argument.startsWith('--')) {throw new Error(`Unknown build option: ${argument}`);}\n const separator = argument.indexOf('=');\n const key = argument.slice(2, separator === -1 ? undefined : separator);\n if (!buildOptionNames.has(key)) {throw new Error(`Unknown build option: --${key}`);}\n if (separator === -1) {throw new Error(`Build option --${key} must use --${key}=value`);}\n values[key] = argument.slice(separator + 1);\n }\n\n let production = false;\n if (values.production !== undefined) {\n if (values.production !== 'true' && values.production !== 'false') {\n throw new Error('Production must be true or false');\n }\n production = values.production === 'true';\n }\n\n return normalizeBuildConfig({\n cdn: values.cdn || '/',\n production,\n siteUrl: values['site-url'] || 'http://localhost:8080',\n version: values.version || String(Math.floor(Date.now() / 1000)),\n www: values.www || '/'\n });\n}\n\n/** Return the local Tailwind executable name for the current platform. */\nexport function tailwindExecutable(platform: NodeJS.Platform = process.platform) {\n return platform === 'win32' ? 'tailwindcss.cmd' : 'tailwindcss';\n}\n\n/** Recursively collect files below a directory, propagating filesystem failures. */\nasync function filesUnder(directory: string): Promise<string[]> {\n const entries = await fs.readdir(directory, {withFileTypes: true});\n const files = await Promise.all(entries.map(async (entry) => {\n const location = path.join(directory, entry.name);\n return entry.isDirectory() ? filesUnder(location) : [location];\n }));\n return files.flat();\n}\n\ninterface PageModule {\n default(data: Record<string, unknown>): {toString(): string} | string;\n}\n\n/** Render compiled TypeScript pages using global, page-specific, and deployment data. */\nasync function renderMarkup(config: BuildConfig, outputRoot: string, projectRoot: string) {\n const globalData = JSON.parse(await fs.readFile(\n path.join(projectRoot, 'app/assets/data/view/global.json'), 'utf8'\n )) as Record<string, unknown>;\n const appRoot = path.join(projectRoot, 'app');\n const pages = (await filesUnder(appRoot))\n .filter((file) => /\\.ts$/.test(file) && !file.endsWith('.d.ts') && !file.includes(`${path.sep}assets${path.sep}`));\n\n await Promise.all(pages.map(async (page) => {\n const relative = path.relative(appRoot, page);\n const pageDataPath = path.join(projectRoot, 'app/assets/data/view', relative.replace(/\\.ts$/, '.json'));\n let pageData: Record<string, unknown> = {};\n try {\n pageData = JSON.parse(await fs.readFile(pageDataPath, 'utf8')) as Record<string, unknown>;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {\n throw error;\n }\n }\n const compiledPage = path.join(projectRoot, 'dist/app', relative.replace(/\\.ts$/, '.js'));\n const module = await import(pathToFileURL(compiledPage).href) as PageModule;\n if (typeof module.default !== 'function') {\n throw new TypeError(`Page module ${relative} must export a default render function`);\n }\n const markup = module.default({...globalData, ...pageData, ...config});\n const destination = path.join(outputRoot, relative.replace(/\\.ts$/, '.html'));\n await fs.mkdir(path.dirname(destination), {recursive: true});\n await fs.writeFile(destination, `<!DOCTYPE html>\\n${String(markup)}\\n`);\n }));\n}\n\n/** Compile Tailwind and project CSS into the deploy directory. */\nasync function compileStyles(outputAssets: string, production: boolean, projectRoot: string) {\n const styleRoot = path.join(projectRoot, 'app/assets/style');\n await fs.mkdir(path.join(outputAssets, 'style'), {recursive: true});\n const destination = path.join(outputAssets, 'style/global.css');\n const argumentsList = [\n '-i', path.join(styleRoot, 'global.css'),\n '-o', destination\n ];\n if (production) {argumentsList.push('--minify');}\n await execFileAsync(tailwindExecutable(), argumentsList, {cwd: projectRoot});\n await fs.copyFile(path.join(styleRoot, 'print.css'), path.join(outputAssets, 'style/print.css'));\n}\n\n/** Bundle plain TypeScript browser entry points, excluding declaration-only files. */\nasync function compileScripts(outputAssets: string, production: boolean, projectRoot: string) {\n const scriptRoot = path.join(projectRoot, 'app/assets/script');\n const entries = (await fs.readdir(scriptRoot, {withFileTypes: true}))\n .filter((entry) => entry.isFile() && !entry.name.endsWith('.d.ts') && entry.name.endsWith('.ts'))\n .map((entry) => path.join(scriptRoot, entry.name));\n await fs.mkdir(path.join(outputAssets, 'script'), {recursive: true});\n await buildJavaScript({\n bundle: true,\n entryNames: '[name].compiled',\n entryPoints: entries,\n format: 'iife',\n loader: {'.ts': 'ts'},\n minify: production,\n outdir: path.join(outputAssets, 'script'),\n sourcemap: !production,\n target: ['es2018']\n });\n await fs.writeFile(path.join(outputAssets, 'script/global.compiled.js'), '');\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\n\n/** Replace the deployment directory with compiled pages, scripts, styles, and static assets. */\nexport async function build(config = parseArguments(process.argv.slice(2)), projectRoot = defaultProjectRoot) {\n const safeConfig = normalizeBuildConfig(config);\n const outputRoot = path.join(projectRoot, '_deploy');\n const outputAssets = path.join(outputRoot, 'release', safeConfig.version, 'assets');\n await fs.rm(outputRoot, {recursive: true, force: true});\n await fs.mkdir(outputAssets, {recursive: true});\n\n await fs.cp(path.join(projectRoot, 'app/assets/data'), path.join(outputAssets, 'data'), {recursive: true});\n await fs.writeFile(path.join(outputAssets, 'data/config.json'), JSON.stringify(safeConfig));\n await renderMarkup(safeConfig, outputRoot, projectRoot);\n await compileStyles(outputAssets, safeConfig.production, projectRoot);\n await compileScripts(outputAssets, safeConfig.production, projectRoot);\n const robots = `User-agent: *\\nAllow: /\\nSitemap: ${safeConfig.siteUrl}/sitemap.xml\\n`;\n await fs.writeFile(path.join(outputRoot, 'robots.txt'), robots);\n const sitemap = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"><url><loc>${escapeXml(`${safeConfig.siteUrl}/`)}</loc></url></urlset>\\n`;\n await fs.writeFile(path.join(outputRoot, 'sitemap.xml'), sitemap);\n}\n\nif (path.resolve(process.argv[1] || '') === fileURLToPath(import.meta.url)) {\n await build();\n}\n"]}
|
package/dist/server/handler.js
CHANGED
|
@@ -43,7 +43,7 @@ export async function handleRequest(request) {
|
|
|
43
43
|
defaultRoute: () => true
|
|
44
44
|
};
|
|
45
45
|
try {
|
|
46
|
-
router.navigate(
|
|
46
|
+
router.navigate(url.toString());
|
|
47
47
|
view.initialize();
|
|
48
48
|
return new Response(`<!doctype html>${view.toString()}`, {
|
|
49
49
|
status: model.get().status,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../server/handler.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AACxC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,yBAAyB,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAC,MAAM,uBAAuB,CAAC;AAQ3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACpB,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,gBAAgB,GAAG,CAAC,QAAQ,GAAG;KAC3C,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QAClB,KAAK;QACL,QAAQ,CAAC,IAAI;YACT,MAAM,KAAK,GAAG,IAAmB,CAAC;YAClC,OAAO,IAAI,CAAA,aAAa,KAAK,CAAC,KAAK,WAAW,KAAK,CAAC,OAAO,aAAa,CAAC;QAC7E,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,MAAM,GAAG;QACZ,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;YAC1B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,6BAA6B;SACzC,CAAC;QACF,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;YACzD,OAAO,KAAK,CAAC,MAAM,CAAC;gBAChB,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,SAAS,IAAI,GAAG;aAC5B,CAAC,CAAC;QACP,CAAC;QACD,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC;IAEF,IAAI,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../server/handler.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AACxC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,yBAAyB,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAC,MAAM,uBAAuB,CAAC;AAQ3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACpB,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,gBAAgB,GAAG,CAAC,QAAQ,GAAG;KAC3C,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QAClB,KAAK;QACL,QAAQ,CAAC,IAAI;YACT,MAAM,KAAK,GAAG,IAAmB,CAAC;YAClC,OAAO,IAAI,CAAA,aAAa,KAAK,CAAC,KAAK,WAAW,KAAK,CAAC,OAAO,aAAa,CAAC;QAC7E,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,MAAM,GAAG;QACZ,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;YAC1B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,6BAA6B;SACzC,CAAC;QACF,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;YACzD,OAAO,KAAK,CAAC,MAAM,CAAC;gBAChB,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,SAAS,IAAI,GAAG;aAC5B,CAAC,CAAC;QACP,CAAC;QACD,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC;IAEF,IAAI,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,QAAQ,CAAC,kBAAkB,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE;YACrD,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM;YAC1B,OAAO,EAAE,EAAC,cAAc,EAAE,0BAA0B,EAAC;SACxD,CAAC,CAAC;IACP,CAAC;YAAS,CAAC;QACP,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC;AACL,CAAC","sourcesContent":["import Mediator from 'white-label-mediator';\nimport {Model} from 'white-label-model';\nimport Router from 'white-label-router';\nimport View from 'white-label-view/server';\nimport {html} from 'white-label-view/html';\n\ntype ServerState = {\n status: number;\n title: string;\n message: string;\n};\n\n/**\n * Provider-neutral serverless example using the Web Request/Response contract.\n *\n * Keep mutable White Label instances request-scoped. Cloud adapters should only\n * translate their provider event into a Request and translate the Response back.\n */\nexport async function handleRequest(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const mediator = new Mediator();\n const model = new Model({\n status: 404,\n title: 'Not found',\n message: `No route for ${url.pathname}.`\n });\n const router = new Router();\n const view = new View({\n model,\n template(data) {\n const state = data as ServerState;\n return html`<main><h1>${state.title}</h1><p>${state.message}</p></main>`;\n }\n });\n\n router.mediator = mediator;\n router.routes = {\n '/health': () => model.update({\n status: 200,\n title: 'Healthy',\n message: 'Serverless request handled.'\n }),\n '/hello': (_scope, location) => {\n const name = String(location.data.query.name ?? 'world');\n return model.update({\n status: 200,\n title: 'Hello',\n message: `Hello ${name}.`\n });\n },\n defaultRoute: () => true\n };\n\n try {\n router.navigate(url.toString());\n view.initialize();\n return new Response(`<!doctype html>${view.toString()}`, {\n status: model.get().status,\n headers: {'content-type': 'text/html; charset=utf-8'}\n });\n } finally {\n view.destroy();\n router.destroy();\n mediator.destroy();\n model.destroy();\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generator-white-label",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.3",
|
|
4
4
|
"description": "Framework-independent TypeScript project generator for accessible, SEO-friendly, HTML-first sites with progressive enhancement, tagged HTML templates, and provider-neutral serverless composition.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/scaffold/index.js",
|
|
@@ -87,10 +87,10 @@
|
|
|
87
87
|
"jsdom": "30.0.1",
|
|
88
88
|
"tailwindcss": "4.3.3",
|
|
89
89
|
"typescript": "7.0.2",
|
|
90
|
-
"white-label-mediator": "5.0.
|
|
91
|
-
"white-label-model": "7.0.
|
|
92
|
-
"white-label-router": "6.1.
|
|
93
|
-
"white-label-view": "7.0.
|
|
90
|
+
"white-label-mediator": "5.0.1",
|
|
91
|
+
"white-label-model": "7.0.3",
|
|
92
|
+
"white-label-router": "6.1.2",
|
|
93
|
+
"white-label-view": "7.0.2"
|
|
94
94
|
},
|
|
95
95
|
"types": "dist/scaffold/index.d.ts",
|
|
96
96
|
"c8": {
|
package/scaffold/AGENTS.md
CHANGED
|
@@ -20,4 +20,4 @@ These instructions are more specific than the repository-root agent guide for fi
|
|
|
20
20
|
|
|
21
21
|
## Coordinated release dependency
|
|
22
22
|
|
|
23
|
-
Generator 10 targets the exact published coordinated runtime versions: `white-label-mediator@5.0.
|
|
23
|
+
Generator 10 targets the exact published coordinated runtime versions: `white-label-mediator@5.0.1`, `white-label-model@7.0.3`, `white-label-router@6.1.2`, and `white-label-view@7.0.2`. Keep the release lockfile registry-based and regenerate it with the package manager when coordinated runtime versions change.
|
package/scaffold/index.ts
CHANGED
|
@@ -18,11 +18,11 @@ export interface CreateProjectOptions {
|
|
|
18
18
|
const nodeFileSystem: ScaffoldFileSystem = {
|
|
19
19
|
async copy(source, destination) {
|
|
20
20
|
await mkdir(path.dirname(destination), {recursive: true});
|
|
21
|
-
await cp(source, destination, {recursive: true});
|
|
21
|
+
await cp(source, destination, {recursive: true, force: false, errorOnExist: true});
|
|
22
22
|
},
|
|
23
23
|
async writeJSON(destination, value) {
|
|
24
24
|
await mkdir(path.dirname(destination), {recursive: true});
|
|
25
|
-
await writeFile(destination, `${JSON.stringify(value, null, 2)}\n
|
|
25
|
+
await writeFile(destination, `${JSON.stringify(value, null, 2)}\n`, {flag: 'wx'});
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -69,10 +69,10 @@ export function createSiteManifest() {
|
|
|
69
69
|
'typescript': '7.0.2'
|
|
70
70
|
},
|
|
71
71
|
dependencies: {
|
|
72
|
-
'white-label-mediator': '5.0.
|
|
73
|
-
'white-label-model': '7.0.
|
|
74
|
-
'white-label-router': '6.1.
|
|
75
|
-
'white-label-view': '7.0.
|
|
72
|
+
'white-label-mediator': '5.0.1',
|
|
73
|
+
'white-label-model': '7.0.3',
|
|
74
|
+
'white-label-router': '6.1.2',
|
|
75
|
+
'white-label-view': '7.0.2'
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
}
|
package/scripts/build.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {build as buildJavaScript} from 'esbuild';
|
|
|
10
10
|
const execFileAsync = promisify(execFile);
|
|
11
11
|
const defaultProjectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
12
12
|
const relativePublicPrefix = /^\/(?!\/)[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/;
|
|
13
|
+
const buildOptionNames = new Set(['cdn', 'production', 'site-url', 'version', 'www']);
|
|
13
14
|
|
|
14
15
|
function hasControlCharacters(value: string): boolean {
|
|
15
16
|
return [...value].some(character => {
|
|
@@ -71,11 +72,24 @@ function normalizeBuildConfig(config: BuildConfig): BuildConfig {
|
|
|
71
72
|
|
|
72
73
|
/** Read deployment flags and reject unsafe or invalid deployment values. */
|
|
73
74
|
export function parseArguments(argumentsList: string[]): BuildConfig {
|
|
74
|
-
const values
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
const values: Record<string, string> = {};
|
|
76
|
+
for (const argument of argumentsList) {
|
|
77
|
+
if (!argument.startsWith('--')) {throw new Error(`Unknown build option: ${argument}`);}
|
|
78
|
+
const separator = argument.indexOf('=');
|
|
79
|
+
const key = argument.slice(2, separator === -1 ? undefined : separator);
|
|
80
|
+
if (!buildOptionNames.has(key)) {throw new Error(`Unknown build option: --${key}`);}
|
|
81
|
+
if (separator === -1) {throw new Error(`Build option --${key} must use --${key}=value`);}
|
|
82
|
+
values[key] = argument.slice(separator + 1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let production = false;
|
|
86
|
+
if (values.production !== undefined) {
|
|
87
|
+
if (values.production !== 'true' && values.production !== 'false') {
|
|
88
|
+
throw new Error('Production must be true or false');
|
|
89
|
+
}
|
|
90
|
+
production = values.production === 'true';
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
return normalizeBuildConfig({
|
|
80
94
|
cdn: values.cdn || '/',
|
|
81
95
|
production,
|
package/server/handler.ts
CHANGED
|
@@ -52,7 +52,7 @@ export async function handleRequest(request: Request): Promise<Response> {
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
try {
|
|
55
|
-
router.navigate(
|
|
55
|
+
router.navigate(url.toString());
|
|
56
56
|
view.initialize();
|
|
57
57
|
return new Response(`<!doctype html>${view.toString()}`, {
|
|
58
58
|
status: model.get().status,
|