@zenithbuild/cli 0.6.5 → 0.6.7
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/dist/build.d.ts +32 -0
- package/dist/build.js +193 -548
- package/dist/compiler-bridge-runner.d.ts +5 -0
- package/dist/compiler-bridge-runner.js +70 -0
- package/dist/component-instance-ir.d.ts +6 -0
- package/dist/component-instance-ir.js +0 -20
- package/dist/component-occurrences.d.ts +6 -0
- package/dist/component-occurrences.js +6 -28
- package/dist/dev-server.d.ts +18 -0
- package/dist/dev-server.js +76 -116
- package/dist/dev-watch.d.ts +1 -0
- package/dist/dev-watch.js +19 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -28
- package/dist/manifest.d.ts +23 -0
- package/dist/manifest.js +22 -48
- package/dist/preview.d.ts +100 -0
- package/dist/preview.js +418 -488
- package/dist/resolve-components.d.ts +39 -0
- package/dist/resolve-components.js +30 -104
- package/dist/server/resolve-request-route.d.ts +39 -0
- package/dist/server/resolve-request-route.js +104 -113
- package/dist/server-contract.d.ts +39 -0
- package/dist/server-contract.js +15 -67
- package/dist/toolchain-paths.d.ts +23 -0
- package/dist/toolchain-paths.js +111 -39
- package/dist/toolchain-runner.d.ts +33 -0
- package/dist/toolchain-runner.js +170 -0
- package/dist/types/generate-env-dts.d.ts +5 -0
- package/dist/types/generate-env-dts.js +4 -2
- package/dist/types/generate-routes-dts.d.ts +8 -0
- package/dist/types/generate-routes-dts.js +7 -5
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.js +16 -7
- package/dist/ui/env.d.ts +18 -0
- package/dist/ui/env.js +0 -12
- package/dist/ui/format.d.ts +33 -0
- package/dist/ui/format.js +7 -45
- package/dist/ui/logger.d.ts +59 -0
- package/dist/ui/logger.js +3 -32
- package/dist/version-check.d.ts +54 -0
- package/dist/version-check.js +41 -98
- package/package.json +17 -5
package/dist/toolchain-paths.js
CHANGED
|
@@ -2,51 +2,94 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
|
|
6
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
6
|
const __dirname = dirname(__filename);
|
|
8
7
|
const CLI_ROOT = resolve(__dirname, '..');
|
|
9
8
|
const localRequire = createRequire(import.meta.url);
|
|
10
|
-
|
|
9
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
10
|
+
const COMPILER_BRIDGE_RUNNER = resolve(__dirname, 'compiler-bridge-runner.js');
|
|
11
11
|
function safeCreateRequire(projectRoot) {
|
|
12
12
|
if (!projectRoot) {
|
|
13
13
|
return localRequire;
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
16
|
return createRequire(resolve(projectRoot, 'package.json'));
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
18
19
|
return localRequire;
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
|
|
22
22
|
function safeResolve(requireFn, specifier) {
|
|
23
23
|
try {
|
|
24
24
|
return requireFn.resolve(specifier);
|
|
25
|
-
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function resolveExecutablePath(candidatePath) {
|
|
31
|
+
if (typeof candidatePath !== 'string' || candidatePath.length === 0) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
if (!IS_WINDOWS || candidatePath.toLowerCase().endsWith('.exe')) {
|
|
35
|
+
return candidatePath;
|
|
36
|
+
}
|
|
37
|
+
if (existsSync(candidatePath)) {
|
|
38
|
+
return candidatePath;
|
|
39
|
+
}
|
|
40
|
+
const exePath = `${candidatePath}.exe`;
|
|
41
|
+
return existsSync(exePath) ? exePath : candidatePath;
|
|
42
|
+
}
|
|
43
|
+
function createBinaryCandidate(tool, source, candidatePath) {
|
|
44
|
+
const resolvedPath = resolveExecutablePath(candidatePath);
|
|
45
|
+
return {
|
|
46
|
+
tool,
|
|
47
|
+
mode: 'binary',
|
|
48
|
+
source,
|
|
49
|
+
sourceKey: `${tool}:${source}:${resolvedPath}`,
|
|
50
|
+
label: source,
|
|
51
|
+
path: resolvedPath,
|
|
52
|
+
command: resolvedPath,
|
|
53
|
+
argsPrefix: []
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function createCompilerBridgeCandidate(modulePath) {
|
|
57
|
+
if (typeof modulePath !== 'string' || modulePath.length === 0) {
|
|
26
58
|
return null;
|
|
27
59
|
}
|
|
60
|
+
return {
|
|
61
|
+
tool: 'compiler',
|
|
62
|
+
mode: 'node-bridge',
|
|
63
|
+
source: 'JS bridge',
|
|
64
|
+
sourceKey: `compiler:js-bridge:${modulePath}`,
|
|
65
|
+
label: 'JS bridge',
|
|
66
|
+
path: modulePath,
|
|
67
|
+
command: process.execPath,
|
|
68
|
+
argsPrefix: [COMPILER_BRIDGE_RUNNER, '--bridge-module', modulePath]
|
|
69
|
+
};
|
|
28
70
|
}
|
|
29
|
-
|
|
30
71
|
export function resolveBinary(candidates) {
|
|
31
72
|
for (const candidate of candidates) {
|
|
32
|
-
|
|
33
|
-
|
|
73
|
+
const path = typeof candidate === 'string' ? candidate : candidate.path;
|
|
74
|
+
if (path && existsSync(path)) {
|
|
75
|
+
return path;
|
|
34
76
|
}
|
|
35
77
|
}
|
|
36
|
-
|
|
78
|
+
const first = candidates[0];
|
|
79
|
+
if (typeof first === 'string') {
|
|
80
|
+
return first;
|
|
81
|
+
}
|
|
82
|
+
return first?.path || '';
|
|
37
83
|
}
|
|
38
|
-
|
|
39
84
|
export function resolvePackageRoot(packageName, projectRoot = null) {
|
|
40
85
|
const projectRequire = safeCreateRequire(projectRoot);
|
|
41
86
|
const projectPath = safeResolve(projectRequire, `${packageName}/package.json`);
|
|
42
87
|
if (projectPath) {
|
|
43
88
|
return dirname(projectPath);
|
|
44
89
|
}
|
|
45
|
-
|
|
46
90
|
const localPath = safeResolve(localRequire, `${packageName}/package.json`);
|
|
47
91
|
return localPath ? dirname(localPath) : null;
|
|
48
92
|
}
|
|
49
|
-
|
|
50
93
|
export function readInstalledPackageVersion(packageName, projectRoot = null) {
|
|
51
94
|
const packageRoot = resolvePackageRoot(packageName, projectRoot);
|
|
52
95
|
if (!packageRoot) {
|
|
@@ -55,56 +98,85 @@ export function readInstalledPackageVersion(packageName, projectRoot = null) {
|
|
|
55
98
|
try {
|
|
56
99
|
const pkg = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8'));
|
|
57
100
|
return typeof pkg.version === 'string' ? pkg.version : null;
|
|
58
|
-
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
59
103
|
return null;
|
|
60
104
|
}
|
|
61
105
|
}
|
|
62
|
-
|
|
63
106
|
export function readCliPackageVersion() {
|
|
64
107
|
try {
|
|
65
108
|
const pkg = JSON.parse(readFileSync(resolve(CLI_ROOT, 'package.json'), 'utf8'));
|
|
66
109
|
return typeof pkg.version === 'string' ? pkg.version : '0.0.0';
|
|
67
|
-
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
68
112
|
return '0.0.0';
|
|
69
113
|
}
|
|
70
114
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
resolve(CLI_ROOT, '../compiler/target/release/zenith-compiler')
|
|
75
|
-
resolve(CLI_ROOT, '../zenith-compiler/target/release/zenith-compiler')
|
|
115
|
+
function compilerWorkspaceBinaryCandidates() {
|
|
116
|
+
return [
|
|
117
|
+
createBinaryCandidate('compiler', 'workspace binary', resolve(CLI_ROOT, '../compiler/target/release/zenith-compiler')),
|
|
118
|
+
createBinaryCandidate('compiler', 'workspace binary', resolve(CLI_ROOT, '../zenith-compiler/target/release/zenith-compiler'))
|
|
76
119
|
];
|
|
120
|
+
}
|
|
121
|
+
function bundlerWorkspaceBinaryCandidates() {
|
|
122
|
+
return [
|
|
123
|
+
createBinaryCandidate('bundler', 'workspace binary', resolve(CLI_ROOT, '../bundler/target/release/zenith-bundler')),
|
|
124
|
+
createBinaryCandidate('bundler', 'workspace binary', resolve(CLI_ROOT, '../zenith-bundler/target/release/zenith-bundler'))
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
export function compilerCommandCandidates(projectRoot = null, env = process.env) {
|
|
128
|
+
const candidates = [];
|
|
129
|
+
const envBin = env.ZENITH_COMPILER_BIN;
|
|
130
|
+
if (typeof envBin === 'string' && envBin.length > 0) {
|
|
131
|
+
candidates.push({
|
|
132
|
+
...createBinaryCandidate('compiler', 'env override (ZENITH_COMPILER_BIN)', envBin),
|
|
133
|
+
explicit: true
|
|
134
|
+
});
|
|
135
|
+
}
|
|
77
136
|
const installedRoot = resolvePackageRoot('@zenithbuild/compiler', projectRoot);
|
|
78
137
|
if (installedRoot) {
|
|
79
|
-
candidates.
|
|
138
|
+
candidates.push(createBinaryCandidate('compiler', 'installed package binary', resolve(installedRoot, 'target/release/zenith-compiler')));
|
|
139
|
+
}
|
|
140
|
+
candidates.push(...compilerWorkspaceBinaryCandidates());
|
|
141
|
+
if (installedRoot) {
|
|
142
|
+
const bridgeCandidate = createCompilerBridgeCandidate(resolve(installedRoot, 'dist/index.js'));
|
|
143
|
+
if (bridgeCandidate) {
|
|
144
|
+
candidates.push(bridgeCandidate);
|
|
145
|
+
}
|
|
80
146
|
}
|
|
81
147
|
return candidates;
|
|
82
148
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
149
|
+
export function compilerBinCandidates(projectRoot = null, env = process.env) {
|
|
150
|
+
return compilerCommandCandidates(projectRoot, env)
|
|
151
|
+
.filter((candidate) => candidate.mode === 'binary')
|
|
152
|
+
.map((candidate) => candidate.path);
|
|
86
153
|
}
|
|
87
|
-
|
|
88
|
-
|
|
154
|
+
export function resolveCompilerBin(projectRoot = null, env = process.env) {
|
|
155
|
+
return resolveBinary(compilerBinCandidates(projectRoot, env));
|
|
156
|
+
}
|
|
157
|
+
export function bundlerCommandCandidates(projectRoot = null, env = process.env) {
|
|
89
158
|
const candidates = [];
|
|
90
|
-
const envBin = env
|
|
159
|
+
const envBin = env.ZENITH_BUNDLER_BIN;
|
|
91
160
|
if (typeof envBin === 'string' && envBin.length > 0) {
|
|
92
|
-
candidates.push(
|
|
161
|
+
candidates.push({
|
|
162
|
+
...createBinaryCandidate('bundler', 'env override (ZENITH_BUNDLER_BIN)', envBin),
|
|
163
|
+
explicit: true
|
|
164
|
+
});
|
|
93
165
|
}
|
|
94
|
-
|
|
95
166
|
const installedRoot = resolvePackageRoot('@zenithbuild/bundler', projectRoot);
|
|
96
167
|
if (installedRoot) {
|
|
97
|
-
candidates.push(resolve(installedRoot, 'target/release/zenith-bundler'));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
candidates.push(
|
|
101
|
-
resolve(CLI_ROOT, '../bundler/target/release/zenith-bundler'),
|
|
102
|
-
resolve(CLI_ROOT, '../zenith-bundler/target/release/zenith-bundler')
|
|
103
|
-
);
|
|
104
|
-
|
|
168
|
+
candidates.push(createBinaryCandidate('bundler', 'installed package binary', resolve(installedRoot, 'target/release/zenith-bundler')));
|
|
169
|
+
}
|
|
170
|
+
candidates.push(...bundlerWorkspaceBinaryCandidates());
|
|
105
171
|
return candidates;
|
|
106
172
|
}
|
|
107
|
-
|
|
108
173
|
export function resolveBundlerBin(projectRoot = null, env = process.env) {
|
|
109
|
-
return resolveBinary(
|
|
174
|
+
return resolveBinary(bundlerCommandCandidates(projectRoot, env)
|
|
175
|
+
.filter((candidate) => candidate.mode === 'binary')
|
|
176
|
+
.map((candidate) => candidate.path));
|
|
177
|
+
}
|
|
178
|
+
export function bundlerBinCandidates(projectRoot = null, env = process.env) {
|
|
179
|
+
return bundlerCommandCandidates(projectRoot, env)
|
|
180
|
+
.filter((candidate) => candidate.mode === 'binary')
|
|
181
|
+
.map((candidate) => candidate.path);
|
|
110
182
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SpawnSyncOptionsWithStringEncoding, SpawnSyncReturns } from 'node:child_process';
|
|
2
|
+
import { type ToolchainCandidate, type ToolchainTool } from './toolchain-paths.js';
|
|
3
|
+
export interface ToolchainLogger {
|
|
4
|
+
warn?: (message: string, options?: {
|
|
5
|
+
onceKey?: string;
|
|
6
|
+
}) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface ToolchainState {
|
|
9
|
+
tool: ToolchainTool;
|
|
10
|
+
logger: ToolchainLogger | null;
|
|
11
|
+
candidates: ToolchainCandidate[];
|
|
12
|
+
activeIndex: number;
|
|
13
|
+
}
|
|
14
|
+
type SpawnResult = SpawnSyncReturns<string>;
|
|
15
|
+
export declare function createCompilerToolchain({ projectRoot, env, logger }?: {
|
|
16
|
+
projectRoot?: string | null;
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
18
|
+
logger?: ToolchainLogger | null;
|
|
19
|
+
}): ToolchainState;
|
|
20
|
+
export declare function createBundlerToolchain({ projectRoot, env, logger }?: {
|
|
21
|
+
projectRoot?: string | null;
|
|
22
|
+
env?: NodeJS.ProcessEnv;
|
|
23
|
+
logger?: ToolchainLogger | null;
|
|
24
|
+
}): ToolchainState;
|
|
25
|
+
export declare function createToolchainStateForTests(tool: ToolchainTool, candidates: ToolchainCandidate[], logger?: ToolchainLogger | null): ToolchainState;
|
|
26
|
+
export declare function resetToolchainWarningsForTests(): void;
|
|
27
|
+
export declare function getActiveToolchainCandidate(toolchain: ToolchainState): ToolchainCandidate | null;
|
|
28
|
+
export declare function ensureToolchainCompatibility(toolchain: ToolchainState, probeArgs?: string[]): ToolchainCandidate;
|
|
29
|
+
export declare function runToolchainSync(toolchain: ToolchainState, args: string[], spawnOptions?: SpawnSyncOptionsWithStringEncoding): {
|
|
30
|
+
result: SpawnResult;
|
|
31
|
+
candidate: ToolchainCandidate;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { bundlerCommandCandidates, compilerCommandCandidates } from './toolchain-paths.js';
|
|
4
|
+
const FALLBACK_LOG_KEYS = new Set();
|
|
5
|
+
const INCOMPATIBLE_ERROR_CODES = new Set(['ENOEXEC', 'EACCES']);
|
|
6
|
+
const INCOMPATIBLE_STDERR_PATTERNS = [
|
|
7
|
+
/exec format error/i,
|
|
8
|
+
/bad cpu type/i,
|
|
9
|
+
/cannot execute binary file/i,
|
|
10
|
+
/not a valid win32 application/i
|
|
11
|
+
];
|
|
12
|
+
function currentPlatformLabel() {
|
|
13
|
+
return `${process.platform}-${process.arch}`;
|
|
14
|
+
}
|
|
15
|
+
function toolEnvVar(tool) {
|
|
16
|
+
return tool === 'bundler' ? 'ZENITH_BUNDLER_BIN' : 'ZENITH_COMPILER_BIN';
|
|
17
|
+
}
|
|
18
|
+
function candidateExists(candidate) {
|
|
19
|
+
if (!candidate) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (candidate.mode === 'node-bridge') {
|
|
23
|
+
const [runnerPath] = candidate.argsPrefix;
|
|
24
|
+
return existsSync(candidate.path) && typeof runnerPath === 'string' && existsSync(runnerPath);
|
|
25
|
+
}
|
|
26
|
+
return typeof candidate.path === 'string' && candidate.path.length > 0 && existsSync(candidate.path);
|
|
27
|
+
}
|
|
28
|
+
function candidateSupportsArgs(candidate, args) {
|
|
29
|
+
if (!candidate || candidate.mode !== 'node-bridge') {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return !args.includes('--embedded-markup-expressions') && !args.includes('--strict-dom-lints');
|
|
33
|
+
}
|
|
34
|
+
function isBinaryIncompatible(result) {
|
|
35
|
+
const error = result?.error;
|
|
36
|
+
const errorCode = error?.code;
|
|
37
|
+
if (typeof errorCode === 'string' && INCOMPATIBLE_ERROR_CODES.has(errorCode)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const stderr = `${result?.stderr || ''}\n${error?.message || ''}`;
|
|
41
|
+
return INCOMPATIBLE_STDERR_PATTERNS.some((pattern) => pattern.test(stderr));
|
|
42
|
+
}
|
|
43
|
+
function emitFallbackWarning(toolchain, nextCandidate) {
|
|
44
|
+
const message = `[zenith] ${toolchain.tool} binary incompatible for this platform; falling back to ${nextCandidate.label}`;
|
|
45
|
+
const onceKey = `toolchain-fallback:${toolchain.tool}:${nextCandidate.sourceKey}`;
|
|
46
|
+
if (toolchain.logger && typeof toolchain.logger.warn === 'function') {
|
|
47
|
+
toolchain.logger.warn(message, { onceKey });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (FALLBACK_LOG_KEYS.has(onceKey)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
FALLBACK_LOG_KEYS.add(onceKey);
|
|
54
|
+
console.warn(message);
|
|
55
|
+
}
|
|
56
|
+
function incompatibleBinaryError(toolchain) {
|
|
57
|
+
return new Error(`[zenith] ${toolchain.tool} binary is incompatible for ${currentPlatformLabel()}; ` +
|
|
58
|
+
`reinstall or set ${toolEnvVar(toolchain.tool)}=...`);
|
|
59
|
+
}
|
|
60
|
+
function toolchainProbeError(toolchain, result) {
|
|
61
|
+
const detail = result?.error?.message
|
|
62
|
+
|| String(result?.stderr || '').trim()
|
|
63
|
+
|| `exit code ${result?.status ?? 'unknown'}`;
|
|
64
|
+
return new Error(`[zenith] ${toolchain.tool} probe failed: ${detail}`);
|
|
65
|
+
}
|
|
66
|
+
function buildToolchainState(tool, candidates, logger = null) {
|
|
67
|
+
const explicitIndex = candidates.findIndex((candidate) => candidate.explicit === true);
|
|
68
|
+
const initialIndex = explicitIndex >= 0
|
|
69
|
+
? explicitIndex
|
|
70
|
+
: candidates.findIndex((candidate) => candidateExists(candidate));
|
|
71
|
+
return {
|
|
72
|
+
tool,
|
|
73
|
+
logger,
|
|
74
|
+
candidates,
|
|
75
|
+
activeIndex: initialIndex >= 0 ? initialIndex : 0
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function findNextFallbackIndex(toolchain, args) {
|
|
79
|
+
for (let index = toolchain.activeIndex + 1; index < toolchain.candidates.length; index += 1) {
|
|
80
|
+
const candidate = toolchain.candidates[index];
|
|
81
|
+
if (!candidateExists(candidate)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (!candidateSupportsArgs(candidate, args)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
return index;
|
|
88
|
+
}
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
function activeCandidate(toolchain) {
|
|
92
|
+
return toolchain.candidates[toolchain.activeIndex] || null;
|
|
93
|
+
}
|
|
94
|
+
function runCandidateSync(candidate, args, spawnOptions) {
|
|
95
|
+
return spawnSync(candidate.command, [...candidate.argsPrefix, ...args], spawnOptions);
|
|
96
|
+
}
|
|
97
|
+
export function createCompilerToolchain({ projectRoot = null, env = process.env, logger = null } = {}) {
|
|
98
|
+
return buildToolchainState('compiler', compilerCommandCandidates(projectRoot, env), logger);
|
|
99
|
+
}
|
|
100
|
+
export function createBundlerToolchain({ projectRoot = null, env = process.env, logger = null } = {}) {
|
|
101
|
+
return buildToolchainState('bundler', bundlerCommandCandidates(projectRoot, env), logger);
|
|
102
|
+
}
|
|
103
|
+
export function createToolchainStateForTests(tool, candidates, logger = null) {
|
|
104
|
+
return buildToolchainState(tool, candidates, logger);
|
|
105
|
+
}
|
|
106
|
+
export function resetToolchainWarningsForTests() {
|
|
107
|
+
FALLBACK_LOG_KEYS.clear();
|
|
108
|
+
}
|
|
109
|
+
export function getActiveToolchainCandidate(toolchain) {
|
|
110
|
+
return activeCandidate(toolchain);
|
|
111
|
+
}
|
|
112
|
+
export function ensureToolchainCompatibility(toolchain, probeArgs = ['--version']) {
|
|
113
|
+
while (toolchain.activeIndex < toolchain.candidates.length) {
|
|
114
|
+
const candidate = activeCandidate(toolchain);
|
|
115
|
+
if (!candidate) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
if (!candidateSupportsArgs(candidate, probeArgs)) {
|
|
119
|
+
const nextIndex = findNextFallbackIndex(toolchain, probeArgs);
|
|
120
|
+
if (nextIndex === -1) {
|
|
121
|
+
throw incompatibleBinaryError(toolchain);
|
|
122
|
+
}
|
|
123
|
+
toolchain.activeIndex = nextIndex;
|
|
124
|
+
emitFallbackWarning(toolchain, toolchain.candidates[nextIndex]);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const result = runCandidateSync(candidate, probeArgs, { encoding: 'utf8' });
|
|
128
|
+
if (!isBinaryIncompatible(result)) {
|
|
129
|
+
if (result.error || result.status !== 0) {
|
|
130
|
+
throw toolchainProbeError(toolchain, result);
|
|
131
|
+
}
|
|
132
|
+
return candidate;
|
|
133
|
+
}
|
|
134
|
+
const nextIndex = findNextFallbackIndex(toolchain, probeArgs);
|
|
135
|
+
if (nextIndex === -1) {
|
|
136
|
+
throw incompatibleBinaryError(toolchain);
|
|
137
|
+
}
|
|
138
|
+
toolchain.activeIndex = nextIndex;
|
|
139
|
+
emitFallbackWarning(toolchain, toolchain.candidates[nextIndex]);
|
|
140
|
+
}
|
|
141
|
+
throw incompatibleBinaryError(toolchain);
|
|
142
|
+
}
|
|
143
|
+
export function runToolchainSync(toolchain, args, spawnOptions = { encoding: 'utf8' }) {
|
|
144
|
+
while (toolchain.activeIndex < toolchain.candidates.length) {
|
|
145
|
+
const candidate = activeCandidate(toolchain);
|
|
146
|
+
if (!candidate) {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
if (!candidateSupportsArgs(candidate, args)) {
|
|
150
|
+
const nextIndex = findNextFallbackIndex(toolchain, args);
|
|
151
|
+
if (nextIndex === -1) {
|
|
152
|
+
throw incompatibleBinaryError(toolchain);
|
|
153
|
+
}
|
|
154
|
+
toolchain.activeIndex = nextIndex;
|
|
155
|
+
emitFallbackWarning(toolchain, toolchain.candidates[nextIndex]);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const result = runCandidateSync(candidate, args, spawnOptions);
|
|
159
|
+
if (!isBinaryIncompatible(result)) {
|
|
160
|
+
return { result, candidate };
|
|
161
|
+
}
|
|
162
|
+
const nextIndex = findNextFallbackIndex(toolchain, args);
|
|
163
|
+
if (nextIndex === -1) {
|
|
164
|
+
throw incompatibleBinaryError(toolchain);
|
|
165
|
+
}
|
|
166
|
+
toolchain.activeIndex = nextIndex;
|
|
167
|
+
emitFallbackWarning(toolchain, toolchain.candidates[nextIndex]);
|
|
168
|
+
}
|
|
169
|
+
throw incompatibleBinaryError(toolchain);
|
|
170
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} projectRoot
|
|
5
|
+
* @returns {Promise<void>}
|
|
6
|
+
*/
|
|
4
7
|
export async function generateEnvDts(projectRoot) {
|
|
5
8
|
const content = `// .zenith/zenith-env.d.ts
|
|
6
9
|
// Auto-generated by Zenith. Do not edit.
|
|
@@ -45,7 +48,6 @@ declare global {
|
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
`;
|
|
48
|
-
|
|
49
51
|
const outPath = join(projectRoot, '.zenith', 'zenith-env.d.ts');
|
|
50
52
|
await mkdir(dirname(outPath), { recursive: true });
|
|
51
53
|
await writeFile(outPath, content, 'utf8');
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} projectRoot
|
|
5
|
+
* @param {Array<{ path?: string | null }>} [manifest]
|
|
6
|
+
* @returns {Promise<void>}
|
|
7
|
+
*/
|
|
4
8
|
export async function generateRoutesDts(projectRoot, manifest) {
|
|
5
|
-
const routes = (manifest || []).map(
|
|
9
|
+
const routes = (manifest || []).map((route) => route.path).filter(Boolean);
|
|
6
10
|
const typeDef = routes.length > 0
|
|
7
|
-
? routes.map(
|
|
11
|
+
? routes.map((route) => `"${route}"`).join(' | ')
|
|
8
12
|
: 'string';
|
|
9
|
-
|
|
10
13
|
const content = '// .zenith/zenith-routes.d.ts\\n' +
|
|
11
14
|
'// Auto-generated by Zenith. Do not edit.\\n\\n' +
|
|
12
15
|
'export {};\\n\\n' +
|
|
@@ -15,7 +18,6 @@ export async function generateRoutesDts(projectRoot, manifest) {
|
|
|
15
18
|
' type RoutePattern = ' + typeDef + ';\\n' +
|
|
16
19
|
' }\\n' +
|
|
17
20
|
'}\\n';
|
|
18
|
-
|
|
19
21
|
const outPath = join(projectRoot, '.zenith', 'zenith-routes.d.ts');
|
|
20
22
|
await mkdir(dirname(outPath), { recursive: true });
|
|
21
23
|
await writeFile(outPath, content, 'utf8');
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {typeof globalThis & { __zenithTypesWarned?: boolean }} ZenithTypesGlobal
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} projectRoot
|
|
6
|
+
* @param {Array<{ path?: string }>} [manifest]
|
|
7
|
+
* @returns {Promise<void>}
|
|
8
|
+
*/
|
|
9
|
+
export function ensureZenithTypes(projectRoot: string, manifest?: Array<{
|
|
10
|
+
path?: string;
|
|
11
|
+
}>): Promise<void>;
|
|
12
|
+
export type ZenithTypesGlobal = typeof globalThis & {
|
|
13
|
+
__zenithTypesWarned?: boolean;
|
|
14
|
+
};
|
package/dist/types/index.js
CHANGED
|
@@ -2,33 +2,42 @@ import { generateEnvDts } from './generate-env-dts.js';
|
|
|
2
2
|
import { generateRoutesDts } from './generate-routes-dts.js';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { access, constants } from 'node:fs/promises';
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {typeof globalThis & { __zenithTypesWarned?: boolean }} ZenithTypesGlobal
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} projectRoot
|
|
10
|
+
* @param {Array<{ path?: string }>} [manifest]
|
|
11
|
+
* @returns {Promise<void>}
|
|
12
|
+
*/
|
|
6
13
|
export async function ensureZenithTypes(projectRoot, manifest) {
|
|
7
14
|
try {
|
|
8
15
|
await generateEnvDts(projectRoot);
|
|
9
16
|
if (manifest) {
|
|
10
17
|
await generateRoutesDts(projectRoot, manifest);
|
|
11
18
|
}
|
|
12
|
-
|
|
13
19
|
// Check if tsconfig.json exists, if it does, check if .zenith is included
|
|
14
20
|
const tsconfigPath = join(projectRoot, 'tsconfig.json');
|
|
15
21
|
let hasTsConfig = false;
|
|
16
22
|
try {
|
|
17
23
|
await access(tsconfigPath, constants.F_OK);
|
|
18
24
|
hasTsConfig = true;
|
|
19
|
-
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
20
27
|
hasTsConfig = false;
|
|
21
28
|
}
|
|
22
|
-
|
|
23
29
|
if (hasTsConfig) {
|
|
24
30
|
// In a real implementation this would parse the JSON and check "include".
|
|
25
31
|
// For now, we simply inform the user to include it if they haven't.
|
|
26
|
-
|
|
32
|
+
/** @type {ZenithTypesGlobal} */
|
|
33
|
+
const globalScope = globalThis;
|
|
34
|
+
if (!globalScope.__zenithTypesWarned) {
|
|
27
35
|
console.warn('\\x1b[33m[zenith]\\x1b[0m For the best TypeScript experience, ensure ".zenith/**/*.d.ts" is in your tsconfig.json "include" array.');
|
|
28
|
-
|
|
36
|
+
globalScope.__zenithTypesWarned = true;
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
|
-
}
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
32
41
|
console.error('[zenith] Failed to generate type definitions:', err);
|
|
33
42
|
}
|
|
34
43
|
}
|
package/dist/ui/env.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type UiLogLevel = 'quiet' | 'normal' | 'verbose';
|
|
2
|
+
export interface UiMode {
|
|
3
|
+
plain: boolean;
|
|
4
|
+
color: boolean;
|
|
5
|
+
tty: boolean;
|
|
6
|
+
ci: boolean;
|
|
7
|
+
spinner: boolean;
|
|
8
|
+
debug: boolean;
|
|
9
|
+
logLevel: UiLogLevel;
|
|
10
|
+
}
|
|
11
|
+
export interface UiRuntime {
|
|
12
|
+
env?: Record<string, string | undefined>;
|
|
13
|
+
stdout?: {
|
|
14
|
+
isTTY?: boolean;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function getUiMode(runtime?: UiRuntime): UiMode;
|
|
18
|
+
export declare function isUiPlain(runtime?: UiRuntime): boolean;
|
package/dist/ui/env.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI environment mode detection for deterministic CLI output.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
function flagEnabled(value) {
|
|
6
2
|
if (value === undefined || value === null) {
|
|
7
3
|
return false;
|
|
@@ -9,7 +5,6 @@ function flagEnabled(value) {
|
|
|
9
5
|
const normalized = String(value).trim().toLowerCase();
|
|
10
6
|
return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
|
|
11
7
|
}
|
|
12
|
-
|
|
13
8
|
function parseLogLevel(value) {
|
|
14
9
|
const normalized = String(value || '').trim().toLowerCase();
|
|
15
10
|
if (normalized === 'quiet' || normalized === 'verbose') {
|
|
@@ -17,10 +12,6 @@ function parseLogLevel(value) {
|
|
|
17
12
|
}
|
|
18
13
|
return 'normal';
|
|
19
14
|
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {{ env?: Record<string, string | undefined>, stdout?: { isTTY?: boolean } }} runtime
|
|
23
|
-
*/
|
|
24
15
|
export function getUiMode(runtime = process) {
|
|
25
16
|
const env = runtime.env || {};
|
|
26
17
|
const tty = Boolean(runtime.stdout?.isTTY);
|
|
@@ -30,7 +21,6 @@ export function getUiMode(runtime = process) {
|
|
|
30
21
|
const forceColor = flagEnabled(env.FORCE_COLOR);
|
|
31
22
|
const debug = flagEnabled(env.ZENITH_DEBUG);
|
|
32
23
|
let logLevel = parseLogLevel(env.ZENITH_LOG_LEVEL);
|
|
33
|
-
|
|
34
24
|
const plain = noUi || ci || !tty;
|
|
35
25
|
const color = !plain && !noColor && (forceColor || tty);
|
|
36
26
|
const spinner = tty && !plain && !ci;
|
|
@@ -40,7 +30,6 @@ export function getUiMode(runtime = process) {
|
|
|
40
30
|
if (debug && logLevel !== 'quiet') {
|
|
41
31
|
logLevel = 'verbose';
|
|
42
32
|
}
|
|
43
|
-
|
|
44
33
|
return {
|
|
45
34
|
plain,
|
|
46
35
|
color,
|
|
@@ -51,7 +40,6 @@ export function getUiMode(runtime = process) {
|
|
|
51
40
|
logLevel
|
|
52
41
|
};
|
|
53
42
|
}
|
|
54
|
-
|
|
55
43
|
export function isUiPlain(runtime = process) {
|
|
56
44
|
return getUiMode(runtime).plain;
|
|
57
45
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import type { UiMode } from './env.js';
|
|
3
|
+
type FormatTag = keyof typeof TAG_COLORS | string;
|
|
4
|
+
interface SummaryRow {
|
|
5
|
+
label?: unknown;
|
|
6
|
+
value?: unknown;
|
|
7
|
+
}
|
|
8
|
+
declare const TAG_COLORS: {
|
|
9
|
+
DEV: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
10
|
+
BUILD: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
11
|
+
HMR: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
12
|
+
ROUTER: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
13
|
+
CSS: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
14
|
+
OK: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
15
|
+
WARN: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
16
|
+
ERR: (colors: ReturnType<typeof pc.createColors>, value: string) => string;
|
|
17
|
+
};
|
|
18
|
+
export declare function formatPrefix(mode: UiMode): string;
|
|
19
|
+
export declare function formatLine(mode: UiMode, { glyph, tag, text }: {
|
|
20
|
+
glyph?: string;
|
|
21
|
+
tag?: FormatTag;
|
|
22
|
+
text?: unknown;
|
|
23
|
+
}): string;
|
|
24
|
+
export declare function formatStep(mode: UiMode, text: unknown, tag?: FormatTag): string;
|
|
25
|
+
export declare function formatHint(mode: UiMode, text: unknown): string;
|
|
26
|
+
export declare function formatHeading(mode: UiMode, text: unknown): string;
|
|
27
|
+
export declare function formatSummaryTable(mode: UiMode, rows: SummaryRow[], tag?: FormatTag): string;
|
|
28
|
+
export declare function sanitizeErrorMessage(input: unknown): string;
|
|
29
|
+
export declare function normalizeErrorMessagePaths(message: string): string;
|
|
30
|
+
export declare function normalizeError(err: unknown): Error;
|
|
31
|
+
export declare function formatErrorBlock(err: unknown, mode: UiMode): string;
|
|
32
|
+
export declare function containsAnsi(value: unknown): boolean;
|
|
33
|
+
export {};
|