@zenithbuild/cli 0.6.17 → 0.7.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.
Files changed (64) hide show
  1. package/dist/build/compiler-runtime.d.ts +59 -0
  2. package/dist/build/compiler-runtime.js +277 -0
  3. package/dist/build/expression-rewrites.d.ts +88 -0
  4. package/dist/build/expression-rewrites.js +372 -0
  5. package/dist/build/hoisted-code-transforms.d.ts +44 -0
  6. package/dist/build/hoisted-code-transforms.js +316 -0
  7. package/dist/build/merge-component-ir.d.ts +16 -0
  8. package/dist/build/merge-component-ir.js +257 -0
  9. package/dist/build/page-component-loop.d.ts +92 -0
  10. package/dist/build/page-component-loop.js +257 -0
  11. package/dist/build/page-ir-normalization.d.ts +23 -0
  12. package/dist/build/page-ir-normalization.js +370 -0
  13. package/dist/build/page-loop-metrics.d.ts +100 -0
  14. package/dist/build/page-loop-metrics.js +131 -0
  15. package/dist/build/page-loop-state.d.ts +261 -0
  16. package/dist/build/page-loop-state.js +92 -0
  17. package/dist/build/page-loop.d.ts +33 -0
  18. package/dist/build/page-loop.js +217 -0
  19. package/dist/build/scoped-identifier-rewrite.d.ts +112 -0
  20. package/dist/build/scoped-identifier-rewrite.js +245 -0
  21. package/dist/build/server-script.d.ts +41 -0
  22. package/dist/build/server-script.js +210 -0
  23. package/dist/build/type-declarations.d.ts +16 -0
  24. package/dist/build/type-declarations.js +158 -0
  25. package/dist/build/typescript-expression-utils.d.ts +23 -0
  26. package/dist/build/typescript-expression-utils.js +272 -0
  27. package/dist/build.d.ts +10 -18
  28. package/dist/build.js +74 -2261
  29. package/dist/component-instance-ir.d.ts +2 -2
  30. package/dist/component-instance-ir.js +146 -39
  31. package/dist/component-occurrences.js +63 -15
  32. package/dist/config.d.ts +66 -0
  33. package/dist/config.js +86 -0
  34. package/dist/debug-script.d.ts +1 -0
  35. package/dist/debug-script.js +8 -0
  36. package/dist/dev-build-session.d.ts +23 -0
  37. package/dist/dev-build-session.js +421 -0
  38. package/dist/dev-server.js +256 -54
  39. package/dist/framework-components/Image.zen +316 -0
  40. package/dist/images/materialize.d.ts +17 -0
  41. package/dist/images/materialize.js +200 -0
  42. package/dist/images/payload.d.ts +18 -0
  43. package/dist/images/payload.js +65 -0
  44. package/dist/images/runtime.d.ts +4 -0
  45. package/dist/images/runtime.js +254 -0
  46. package/dist/images/service.d.ts +4 -0
  47. package/dist/images/service.js +302 -0
  48. package/dist/images/shared.d.ts +58 -0
  49. package/dist/images/shared.js +306 -0
  50. package/dist/index.js +2 -17
  51. package/dist/manifest.js +45 -0
  52. package/dist/preview.d.ts +4 -1
  53. package/dist/preview.js +59 -6
  54. package/dist/resolve-components.js +20 -3
  55. package/dist/server-contract.js +3 -2
  56. package/dist/server-script-composition.d.ts +39 -0
  57. package/dist/server-script-composition.js +133 -0
  58. package/dist/startup-profile.d.ts +10 -0
  59. package/dist/startup-profile.js +62 -0
  60. package/dist/toolchain-paths.d.ts +1 -0
  61. package/dist/toolchain-paths.js +31 -0
  62. package/dist/version-check.d.ts +2 -1
  63. package/dist/version-check.js +12 -5
  64. package/package.json +5 -4
@@ -0,0 +1,133 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { basename, dirname, extname, join, relative } from 'node:path';
3
+ const DATA_EXPORT_RE = /\bexport\s+const\s+data\b/;
4
+ const LEGACY_EXPORT_RE = /\bexport\s+const\s+(?:ssr_data|props|ssr)\b/;
5
+ /**
6
+ * @param {string} sourceFile
7
+ * @param {'guard' | 'load'} kind
8
+ * @returns {string[]}
9
+ */
10
+ function adjacentModuleCandidates(sourceFile, kind) {
11
+ const dir = dirname(sourceFile);
12
+ const stem = basename(sourceFile, extname(sourceFile));
13
+ const baseName = sourceFile.slice(0, -extname(sourceFile).length);
14
+ const candidates = [];
15
+ if (stem === 'index') {
16
+ candidates.push(join(dir, `page.${kind}.ts`));
17
+ candidates.push(join(dir, `page.${kind}.js`));
18
+ }
19
+ candidates.push(`${baseName}.${kind}.ts`);
20
+ candidates.push(`${baseName}.${kind}.js`);
21
+ return candidates;
22
+ }
23
+ /**
24
+ * @param {string} sourceFile
25
+ * @param {'guard' | 'load'} kind
26
+ * @returns {string | null}
27
+ */
28
+ function resolveAdjacentModule(sourceFile, kind) {
29
+ const matches = adjacentModuleCandidates(sourceFile, kind).filter((candidate) => existsSync(candidate));
30
+ if (matches.length === 0) {
31
+ return null;
32
+ }
33
+ if (matches.length > 1) {
34
+ throw new Error(`Zenith server script contract violation:\n` +
35
+ ` File: ${sourceFile}\n` +
36
+ ` Reason: multiple adjacent ${kind} modules detected\n` +
37
+ ` Matches: ${matches.join(', ')}\n` +
38
+ ` Example: keep exactly one adjacent ${kind} module for this route`);
39
+ }
40
+ return matches[0];
41
+ }
42
+ /**
43
+ * @param {string} fromFile
44
+ * @param {string} targetFile
45
+ * @returns {string}
46
+ */
47
+ function renderRelativeSpecifier(fromFile, targetFile) {
48
+ let specifier = relative(dirname(fromFile), targetFile).replaceAll('\\', '/');
49
+ if (!specifier.startsWith('.')) {
50
+ specifier = `./${specifier}`;
51
+ }
52
+ return specifier;
53
+ }
54
+ /**
55
+ * @param {string} source
56
+ * @returns {{ hasData: boolean, hasLegacy: boolean }}
57
+ */
58
+ function classifyInlineServerSource(source) {
59
+ const input = String(source || '');
60
+ return {
61
+ hasData: DATA_EXPORT_RE.test(input),
62
+ hasLegacy: LEGACY_EXPORT_RE.test(input)
63
+ };
64
+ }
65
+ /**
66
+ * @param {{
67
+ * sourceFile: string,
68
+ * inlineServerScript?: { source: string, prerender: boolean, has_guard: boolean, has_load: boolean, source_path: string } | null,
69
+ * adjacentGuardPath?: string | null,
70
+ * adjacentLoadPath?: string | null
71
+ * }} input
72
+ * @returns {{ serverScript: { source: string, prerender: boolean, has_guard: boolean, has_load: boolean, source_path: string } | null, guardPath: string | null, loadPath: string | null }}
73
+ */
74
+ export function composeServerScriptEnvelope({ sourceFile, inlineServerScript = null, adjacentGuardPath = null, adjacentLoadPath = null }) {
75
+ const inlineSource = String(inlineServerScript?.source || '').trim();
76
+ const inlineHasGuard = inlineServerScript?.has_guard === true;
77
+ const inlineHasLoad = inlineServerScript?.has_load === true;
78
+ const { hasData, hasLegacy } = classifyInlineServerSource(inlineSource);
79
+ if (inlineHasGuard && adjacentGuardPath) {
80
+ throw new Error(`Zenith server script contract violation:\n` +
81
+ ` File: ${sourceFile}\n` +
82
+ ` Reason: guard is defined both inline and in an adjacent module\n` +
83
+ ` Example: keep guard in either <script server> or ${basename(adjacentGuardPath)}, not both`);
84
+ }
85
+ if (inlineHasLoad && adjacentLoadPath) {
86
+ throw new Error(`Zenith server script contract violation:\n` +
87
+ ` File: ${sourceFile}\n` +
88
+ ` Reason: load is defined both inline and in an adjacent module\n` +
89
+ ` Example: keep load in either <script server> or ${basename(adjacentLoadPath)}, not both`);
90
+ }
91
+ if (adjacentLoadPath && (hasData || hasLegacy)) {
92
+ throw new Error(`Zenith server script contract violation:\n` +
93
+ ` File: ${sourceFile}\n` +
94
+ ` Reason: an adjacent load module cannot be combined with inline data/legacy payload exports\n` +
95
+ ` Example: remove export const data/ssr_data/props/ssr or move payload logic into load(ctx)`);
96
+ }
97
+ const prologue = [];
98
+ if (adjacentGuardPath) {
99
+ prologue.push(`export { guard } from '${renderRelativeSpecifier(sourceFile, adjacentGuardPath)}';`);
100
+ }
101
+ if (adjacentLoadPath) {
102
+ prologue.push(`export { load } from '${renderRelativeSpecifier(sourceFile, adjacentLoadPath)}';`);
103
+ }
104
+ const mergedSource = [...prologue, inlineSource].filter(Boolean).join('\n');
105
+ if (!mergedSource.trim()) {
106
+ return {
107
+ serverScript: null,
108
+ guardPath: adjacentGuardPath,
109
+ loadPath: adjacentLoadPath
110
+ };
111
+ }
112
+ return {
113
+ serverScript: {
114
+ source: mergedSource,
115
+ prerender: inlineServerScript?.prerender === true,
116
+ has_guard: inlineHasGuard || Boolean(adjacentGuardPath),
117
+ has_load: inlineHasLoad || Boolean(adjacentLoadPath),
118
+ source_path: sourceFile
119
+ },
120
+ guardPath: adjacentGuardPath,
121
+ loadPath: adjacentLoadPath
122
+ };
123
+ }
124
+ /**
125
+ * @param {string} sourceFile
126
+ * @returns {{ guardPath: string | null, loadPath: string | null }}
127
+ */
128
+ export function resolveAdjacentServerModules(sourceFile) {
129
+ return {
130
+ guardPath: resolveAdjacentModule(sourceFile, 'guard'),
131
+ loadPath: resolveAdjacentModule(sourceFile, 'load')
132
+ };
133
+ }
@@ -0,0 +1,10 @@
1
+ export function createStartupProfiler(scope: any): {
2
+ enabled: boolean;
3
+ emit: (event: any, payload?: {}) => void;
4
+ measureSync: (label: any, fn: any, payload?: {}) => any;
5
+ measureAsync: (label: any, fn: any, payload?: {}) => Promise<any>;
6
+ nowMs(): number;
7
+ roundMs: typeof roundMs;
8
+ };
9
+ declare function roundMs(value: any): number;
10
+ export {};
@@ -0,0 +1,62 @@
1
+ import { performance } from 'node:perf_hooks';
2
+ const STARTUP_PROFILE_ENV = 'ZENITH_STARTUP_PROFILE';
3
+ function roundMs(value) {
4
+ return Math.round(Number(value || 0) * 100) / 100;
5
+ }
6
+ export function createStartupProfiler(scope) {
7
+ const enabled = process.env[STARTUP_PROFILE_ENV] === '1';
8
+ const startedAt = performance.now();
9
+ function emit(event, payload = {}) {
10
+ if (!enabled) {
11
+ return;
12
+ }
13
+ const record = {
14
+ scope,
15
+ event,
16
+ atMs: roundMs(performance.now() - startedAt),
17
+ ...payload
18
+ };
19
+ try {
20
+ console.error(`[zenith-startup] ${JSON.stringify(record)}`);
21
+ }
22
+ catch {
23
+ // profiling must never break runtime behavior
24
+ }
25
+ }
26
+ function measureSync(label, fn, payload = {}) {
27
+ const stepStartedAt = performance.now();
28
+ try {
29
+ return fn();
30
+ }
31
+ finally {
32
+ emit('step', {
33
+ label,
34
+ durationMs: roundMs(performance.now() - stepStartedAt),
35
+ ...payload
36
+ });
37
+ }
38
+ }
39
+ async function measureAsync(label, fn, payload = {}) {
40
+ const stepStartedAt = performance.now();
41
+ try {
42
+ return await fn();
43
+ }
44
+ finally {
45
+ emit('step', {
46
+ label,
47
+ durationMs: roundMs(performance.now() - stepStartedAt),
48
+ ...payload
49
+ });
50
+ }
51
+ }
52
+ return {
53
+ enabled,
54
+ emit,
55
+ measureSync,
56
+ measureAsync,
57
+ nowMs() {
58
+ return roundMs(performance.now() - startedAt);
59
+ },
60
+ roundMs
61
+ };
62
+ }
@@ -15,6 +15,7 @@ export declare function resolveBinary(candidates: Array<string | ToolchainCandid
15
15
  export declare function resolvePackageRoot(packageName: string, projectRoot?: string | null): string | null;
16
16
  export declare function readInstalledPackageVersion(packageName: string, projectRoot?: string | null): string | null;
17
17
  export declare function readCliPackageVersion(): string;
18
+ export declare function readWorkspacePackageVersion(packageName: string): string | null;
18
19
  export declare function compilerCommandCandidates(projectRoot?: string | null, env?: NodeJS.ProcessEnv): ToolchainCandidate[];
19
20
  export declare function compilerBinCandidates(projectRoot?: string | null, env?: NodeJS.ProcessEnv): string[];
20
21
  export declare function resolveCompilerBin(projectRoot?: string | null, env?: NodeJS.ProcessEnv): string;
@@ -151,6 +151,37 @@ export function readCliPackageVersion() {
151
151
  return '0.0.0';
152
152
  }
153
153
  }
154
+ function workspacePackageManifestPath(packageName) {
155
+ switch (packageName) {
156
+ case '@zenithbuild/cli':
157
+ return resolve(CLI_ROOT, 'package.json');
158
+ case '@zenithbuild/core':
159
+ return resolve(CLI_ROOT, '../core/package.json');
160
+ case '@zenithbuild/compiler':
161
+ return resolve(CLI_ROOT, '../compiler/package.json');
162
+ case '@zenithbuild/runtime':
163
+ return resolve(CLI_ROOT, '../runtime/package.json');
164
+ case '@zenithbuild/router':
165
+ return resolve(CLI_ROOT, '../router/package.json');
166
+ case '@zenithbuild/bundler':
167
+ return resolve(CLI_ROOT, '../bundler/package.json');
168
+ default:
169
+ return '';
170
+ }
171
+ }
172
+ export function readWorkspacePackageVersion(packageName) {
173
+ const manifestPath = workspacePackageManifestPath(packageName);
174
+ if (!manifestPath || !existsSync(manifestPath)) {
175
+ return null;
176
+ }
177
+ try {
178
+ const pkg = JSON.parse(readFileSync(manifestPath, 'utf8'));
179
+ return typeof pkg.version === 'string' ? pkg.version : null;
180
+ }
181
+ catch {
182
+ return null;
183
+ }
184
+ }
154
185
  function createInstalledPlatformPackageCandidate(tool, packages, projectRoot) {
155
186
  const platformPackage = currentPlatformPackage(packages);
156
187
  if (!platformPackage) {
@@ -40,9 +40,10 @@ interface VersionCheckLogger {
40
40
  }
41
41
  export declare function compareVersions(leftVersion: string | null | undefined, rightVersion: string | null | undefined): number;
42
42
  export declare function getBundlerVersion(bundlerBinPath: string | null | undefined): BundlerVersionResult;
43
- export declare function getLocalZenithVersions({ projectRoot, bundlerBinPath }?: {
43
+ export declare function getLocalZenithVersions({ projectRoot, bundlerBinPath, preferWorkspacePackageVersions }?: {
44
44
  projectRoot?: string | null;
45
45
  bundlerBinPath?: string | null;
46
+ preferWorkspacePackageVersions?: boolean;
46
47
  }): ZenithVersions;
47
48
  export declare function checkCompatibility(versions: Partial<ZenithVersions>): CompatibilityResult;
48
49
  export declare function maybeWarnAboutZenithVersionMismatch({ projectRoot, logger, command, bundlerBinPath }?: {
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { readCliPackageVersion, readInstalledPackageVersion, resolveBundlerBin } from './toolchain-paths.js';
4
+ import { readCliPackageVersion, readInstalledPackageVersion, readWorkspacePackageVersion, resolveBundlerBin } from './toolchain-paths.js';
5
5
  const PACKAGE_KEYS = [
6
6
  ['core', '@zenithbuild/core'],
7
7
  ['compiler', '@zenithbuild/compiler'],
@@ -220,12 +220,18 @@ export function getBundlerVersion(bundlerBinPath) {
220
220
  ok: result.status === 0 && Boolean(versionMatch)
221
221
  };
222
222
  }
223
- export function getLocalZenithVersions({ projectRoot, bundlerBinPath } = {}) {
223
+ export function getLocalZenithVersions({ projectRoot, bundlerBinPath, preferWorkspacePackageVersions = false } = {}) {
224
224
  const resolvedBundlerBin = bundlerBinPath || resolveBundlerBin(projectRoot ?? null);
225
225
  const bundlerVersion = getBundlerVersion(resolvedBundlerBin);
226
+ const readPackageVersion = (packageName) => {
227
+ if (preferWorkspacePackageVersions) {
228
+ return readWorkspacePackageVersion(packageName) || readInstalledPackageVersion(packageName, projectRoot ?? null);
229
+ }
230
+ return readInstalledPackageVersion(packageName, projectRoot ?? null);
231
+ };
226
232
  const versions = {
227
233
  cli: readCliPackageVersion(),
228
- projectCli: readInstalledPackageVersion('@zenithbuild/cli', projectRoot ?? null),
234
+ projectCli: readPackageVersion('@zenithbuild/cli'),
229
235
  core: null,
230
236
  compiler: null,
231
237
  runtime: null,
@@ -237,7 +243,7 @@ export function getLocalZenithVersions({ projectRoot, bundlerBinPath } = {}) {
237
243
  targetVersion: null
238
244
  };
239
245
  for (const [key, packageName] of PACKAGE_KEYS) {
240
- versions[key] = readInstalledPackageVersion(packageName, projectRoot ?? null);
246
+ versions[key] = readPackageVersion(packageName);
241
247
  }
242
248
  versions.targetVersion = determineTargetVersion(versions);
243
249
  return versions;
@@ -299,7 +305,8 @@ export async function maybeWarnAboutZenithVersionMismatch({ projectRoot, logger,
299
305
  if (!logger || process.env.ZENITH_SKIP_VERSION_CHECK === '1') {
300
306
  return { status: 'ok', issues: [], details: { targetVersion: '0.0.0', versions: {}, summary: '' } };
301
307
  }
302
- const versions = getLocalZenithVersions({ projectRoot, bundlerBinPath });
308
+ const preferWorkspacePackageVersions = process.env.ZENITH_PREFER_WORKSPACE_PACKAGES === '1';
309
+ const versions = getLocalZenithVersions({ projectRoot, bundlerBinPath, preferWorkspacePackageVersions });
303
310
  versions.projectRoot = projectRoot ?? null;
304
311
  const result = checkCompatibility(versions);
305
312
  const onceKey = `zenith-version-check:${describeVersions(versions)}:${result.status}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenithbuild/cli",
3
- "version": "0.6.17",
3
+ "version": "0.7.0",
4
4
  "description": "Deterministic project orchestrator for Zenith framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,14 +28,15 @@
28
28
  "access": "public"
29
29
  },
30
30
  "scripts": {
31
- "build": "rm -rf dist && tsc -p tsconfig.build.json && node -e \"const fs=require('fs');if(fs.existsSync('dist/index.js')) fs.chmodSync('dist/index.js',0o755)\"",
31
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node ./scripts/copy-framework-components.mjs && node -e \"const fs=require('fs');if(fs.existsSync('dist/index.js')) fs.chmodSync('dist/index.js',0o755)\"",
32
32
  "typecheck": "tsc -p tsconfig.json --noEmit",
33
33
  "test": "bun run build && node --experimental-vm-modules $(node -e \"const path=require('node:path');const pkg=require.resolve('jest/package.json');process.stdout.write(path.join(path.dirname(pkg),'bin/jest.js'))\") --config jest.config.js --forceExit --runInBand",
34
34
  "prepublishOnly": "npm run build"
35
35
  },
36
36
  "dependencies": {
37
- "@zenithbuild/compiler": "0.6.17",
38
- "picocolors": "^1.1.1"
37
+ "@zenithbuild/compiler": "0.7.0",
38
+ "picocolors": "^1.1.1",
39
+ "sharp": "^0.34.4"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@types/node": "latest",