@zenithbuild/cli 0.6.6 → 0.6.9
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 +65 -114
- package/dist/dev-watch.d.ts +1 -0
- package/dist/dev-watch.js +2 -2
- 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 +139 -39
- package/dist/toolchain-runner.d.ts +33 -0
- package/dist/toolchain-runner.js +194 -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 +8 -46
- 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 +6 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {{ bridgeModule: string, filePath: string, stdin: boolean }} BridgeArgs
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @param {string[]} argv
|
|
8
|
+
* @returns {BridgeArgs}
|
|
9
|
+
*/
|
|
10
|
+
function readArgs(argv) {
|
|
11
|
+
/** @type {BridgeArgs} */
|
|
12
|
+
const args = {
|
|
13
|
+
bridgeModule: '',
|
|
14
|
+
filePath: '',
|
|
15
|
+
stdin: false
|
|
16
|
+
};
|
|
17
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
18
|
+
const token = argv[index];
|
|
19
|
+
if (token === '--bridge-module') {
|
|
20
|
+
args.bridgeModule = argv[index + 1] || '';
|
|
21
|
+
index += 1;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (token === '--stdin') {
|
|
25
|
+
args.stdin = true;
|
|
26
|
+
args.filePath = argv[index + 1] || '';
|
|
27
|
+
index += 1;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (!token.startsWith('--') && !args.filePath) {
|
|
31
|
+
args.filePath = token;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return args;
|
|
35
|
+
}
|
|
36
|
+
async function readStdin() {
|
|
37
|
+
const chunks = [];
|
|
38
|
+
for await (const chunk of process.stdin) {
|
|
39
|
+
chunks.push(typeof chunk === 'string' ? chunk : chunk.toString('utf8'));
|
|
40
|
+
}
|
|
41
|
+
return chunks.join('');
|
|
42
|
+
}
|
|
43
|
+
async function main() {
|
|
44
|
+
const args = readArgs(process.argv.slice(2));
|
|
45
|
+
if (!args.bridgeModule) {
|
|
46
|
+
throw new Error('Missing --bridge-module');
|
|
47
|
+
}
|
|
48
|
+
if (!args.filePath) {
|
|
49
|
+
throw new Error('Missing compiler file path');
|
|
50
|
+
}
|
|
51
|
+
const bridgeModuleUrl = pathToFileURL(args.bridgeModule).href;
|
|
52
|
+
const bridgeModule = await import(bridgeModuleUrl);
|
|
53
|
+
if (typeof bridgeModule.compile !== 'function') {
|
|
54
|
+
throw new Error('Compiler bridge does not export compile()');
|
|
55
|
+
}
|
|
56
|
+
const result = args.stdin
|
|
57
|
+
? await bridgeModule.compile({
|
|
58
|
+
source: await readStdin(),
|
|
59
|
+
filePath: args.filePath
|
|
60
|
+
})
|
|
61
|
+
: await bridgeModule.compile(args.filePath);
|
|
62
|
+
process.stdout.write(JSON.stringify(result));
|
|
63
|
+
}
|
|
64
|
+
main().catch((error) => {
|
|
65
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
66
|
+
if (message) {
|
|
67
|
+
process.stderr.write(`${message}\n`);
|
|
68
|
+
}
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export function cloneComponentIrForInstance(compIr: any, instanceId: any, extractDeclaredIdentifiers: any, resolveStateKeyFromBindings: any): {
|
|
2
|
+
ir: any;
|
|
3
|
+
renameMap: Map<any, string>;
|
|
4
|
+
refIdentifierPairs: any;
|
|
5
|
+
};
|
|
6
|
+
export function applyOccurrenceRewritePlans(pageIr: any, occurrencePlans: any, resolveBindingMetadata: any): void;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
function deepClone(value) {
|
|
2
2
|
return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
|
|
3
3
|
}
|
|
4
|
-
|
|
5
4
|
function escapeIdentifier(identifier) {
|
|
6
5
|
return identifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
7
6
|
}
|
|
8
|
-
|
|
9
7
|
function replaceIdentifierRefs(input, renameMap) {
|
|
10
8
|
let output = String(input || '');
|
|
11
9
|
const entries = [...renameMap.entries()].sort((a, b) => b[0].length - a[0].length);
|
|
@@ -15,31 +13,26 @@ function replaceIdentifierRefs(input, renameMap) {
|
|
|
15
13
|
}
|
|
16
14
|
return output;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
16
|
function collectRenameTargets(compIr, extractDeclaredIdentifiers) {
|
|
20
17
|
const targets = new Set();
|
|
21
|
-
|
|
22
18
|
const stateBindings = Array.isArray(compIr?.hoisted?.state) ? compIr.hoisted.state : [];
|
|
23
19
|
for (const entry of stateBindings) {
|
|
24
20
|
if (typeof entry?.key === 'string' && entry.key.length > 0) {
|
|
25
21
|
targets.add(entry.key);
|
|
26
22
|
}
|
|
27
23
|
}
|
|
28
|
-
|
|
29
24
|
const functions = Array.isArray(compIr?.hoisted?.functions) ? compIr.hoisted.functions : [];
|
|
30
25
|
for (const fnName of functions) {
|
|
31
26
|
if (typeof fnName === 'string' && fnName.length > 0) {
|
|
32
27
|
targets.add(fnName);
|
|
33
28
|
}
|
|
34
29
|
}
|
|
35
|
-
|
|
36
30
|
const signals = Array.isArray(compIr?.hoisted?.signals) ? compIr.hoisted.signals : [];
|
|
37
31
|
for (const signalName of signals) {
|
|
38
32
|
if (typeof signalName === 'string' && signalName.length > 0) {
|
|
39
33
|
targets.add(signalName);
|
|
40
34
|
}
|
|
41
35
|
}
|
|
42
|
-
|
|
43
36
|
const declarations = Array.isArray(compIr?.hoisted?.declarations) ? compIr.hoisted.declarations : [];
|
|
44
37
|
for (const declaration of declarations) {
|
|
45
38
|
if (typeof declaration !== 'string') {
|
|
@@ -49,14 +42,11 @@ function collectRenameTargets(compIr, extractDeclaredIdentifiers) {
|
|
|
49
42
|
targets.add(identifier);
|
|
50
43
|
}
|
|
51
44
|
}
|
|
52
|
-
|
|
53
45
|
return [...targets];
|
|
54
46
|
}
|
|
55
|
-
|
|
56
47
|
function buildRefIdentifierMap(baseIr, renameMap, resolveStateKeyFromBindings) {
|
|
57
48
|
const baseState = Array.isArray(baseIr?.hoisted?.state) ? baseIr.hoisted.state : [];
|
|
58
49
|
const baseRefs = Array.isArray(baseIr?.ref_bindings) ? baseIr.ref_bindings : [];
|
|
59
|
-
|
|
60
50
|
return baseRefs.map((binding) => {
|
|
61
51
|
const raw = typeof binding?.identifier === 'string' ? binding.identifier : null;
|
|
62
52
|
const resolvedBase = raw ? resolveStateKeyFromBindings(raw, baseState) : null;
|
|
@@ -67,17 +57,14 @@ function buildRefIdentifierMap(baseIr, renameMap, resolveStateKeyFromBindings) {
|
|
|
67
57
|
};
|
|
68
58
|
}).filter((entry) => typeof entry.raw === 'string' && typeof entry.rewritten === 'string');
|
|
69
59
|
}
|
|
70
|
-
|
|
71
60
|
export function cloneComponentIrForInstance(compIr, instanceId, extractDeclaredIdentifiers, resolveStateKeyFromBindings) {
|
|
72
61
|
const suffix = `__inst${instanceId}`;
|
|
73
62
|
const cloned = deepClone(compIr);
|
|
74
63
|
const renameTargets = collectRenameTargets(compIr, extractDeclaredIdentifiers);
|
|
75
64
|
const renameMap = new Map(renameTargets.map((name) => [name, `${name}${suffix}`]));
|
|
76
|
-
|
|
77
65
|
if (Array.isArray(cloned?.expressions)) {
|
|
78
66
|
cloned.expressions = cloned.expressions.map((expr) => replaceIdentifierRefs(expr, renameMap));
|
|
79
67
|
}
|
|
80
|
-
|
|
81
68
|
if (Array.isArray(cloned?.expression_bindings)) {
|
|
82
69
|
cloned.expression_bindings = cloned.expression_bindings.map((binding) => {
|
|
83
70
|
if (!binding || typeof binding !== 'object') {
|
|
@@ -98,7 +85,6 @@ export function cloneComponentIrForInstance(compIr, instanceId, extractDeclaredI
|
|
|
98
85
|
};
|
|
99
86
|
});
|
|
100
87
|
}
|
|
101
|
-
|
|
102
88
|
if (cloned?.hoisted) {
|
|
103
89
|
if (Array.isArray(cloned.hoisted.declarations)) {
|
|
104
90
|
cloned.hoisted.declarations = cloned.hoisted.declarations.map((line) => replaceIdentifierRefs(line, renameMap));
|
|
@@ -123,7 +109,6 @@ export function cloneComponentIrForInstance(compIr, instanceId, extractDeclaredI
|
|
|
123
109
|
cloned.hoisted.code = cloned.hoisted.code.map((line) => replaceIdentifierRefs(line, renameMap));
|
|
124
110
|
}
|
|
125
111
|
}
|
|
126
|
-
|
|
127
112
|
if (Array.isArray(cloned?.ref_bindings)) {
|
|
128
113
|
const clonedState = Array.isArray(cloned?.hoisted?.state) ? cloned.hoisted.state : [];
|
|
129
114
|
cloned.ref_bindings = cloned.ref_bindings.map((binding) => {
|
|
@@ -137,7 +122,6 @@ export function cloneComponentIrForInstance(compIr, instanceId, extractDeclaredI
|
|
|
137
122
|
};
|
|
138
123
|
});
|
|
139
124
|
}
|
|
140
|
-
|
|
141
125
|
const refIdentifierPairs = buildRefIdentifierMap(compIr, renameMap, resolveStateKeyFromBindings);
|
|
142
126
|
return {
|
|
143
127
|
ir: cloned,
|
|
@@ -145,15 +129,12 @@ export function cloneComponentIrForInstance(compIr, instanceId, extractDeclaredI
|
|
|
145
129
|
refIdentifierPairs
|
|
146
130
|
};
|
|
147
131
|
}
|
|
148
|
-
|
|
149
132
|
export function applyOccurrenceRewritePlans(pageIr, occurrencePlans, resolveBindingMetadata) {
|
|
150
133
|
const expressions = Array.isArray(pageIr?.expressions) ? pageIr.expressions : [];
|
|
151
134
|
const bindings = Array.isArray(pageIr?.expression_bindings) ? pageIr.expression_bindings : [];
|
|
152
135
|
const refBindings = Array.isArray(pageIr?.ref_bindings) ? pageIr.ref_bindings : [];
|
|
153
|
-
|
|
154
136
|
let exprCursor = 0;
|
|
155
137
|
let refCursor = 0;
|
|
156
|
-
|
|
157
138
|
for (const plan of occurrencePlans) {
|
|
158
139
|
const sequence = Array.isArray(plan?.expressionSequence) ? plan.expressionSequence : [];
|
|
159
140
|
for (const item of sequence) {
|
|
@@ -194,7 +175,6 @@ export function applyOccurrenceRewritePlans(pageIr, occurrencePlans, resolveBind
|
|
|
194
175
|
}
|
|
195
176
|
exprCursor = found + 1;
|
|
196
177
|
}
|
|
197
|
-
|
|
198
178
|
const refSequence = Array.isArray(plan?.refSequence) ? plan.refSequence : [];
|
|
199
179
|
for (const refItem of refSequence) {
|
|
200
180
|
if (typeof refItem?.raw !== 'string' || typeof refItem?.rewritten !== 'string') {
|
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { extractTemplate, isDocumentMode } from './resolve-components.js';
|
|
3
|
-
|
|
4
3
|
const OPEN_COMPONENT_TAG_RE = /<([A-Z][a-zA-Z0-9]*)(\s[^<>]*?)?\s*(\/?)>/g;
|
|
5
|
-
|
|
6
4
|
export function collectExpandedComponentOccurrences(source, registry, sourceFile) {
|
|
7
5
|
/** @type {Array<{ name: string, attrs: string, ownerPath: string, componentPath: string }>} */
|
|
8
6
|
const occurrences = [];
|
|
9
7
|
walkSource(String(source || ''), registry, sourceFile, [], occurrences);
|
|
10
8
|
return occurrences;
|
|
11
9
|
}
|
|
12
|
-
|
|
13
10
|
function walkSource(source, registry, sourceFile, chain, occurrences) {
|
|
14
11
|
let cursor = 0;
|
|
15
|
-
|
|
16
12
|
while (cursor < source.length) {
|
|
17
13
|
const tag = findNextKnownTag(source, registry, cursor);
|
|
18
14
|
if (!tag) {
|
|
19
15
|
return;
|
|
20
16
|
}
|
|
21
|
-
|
|
22
17
|
let children = '';
|
|
23
18
|
let replaceEnd = tag.end;
|
|
24
19
|
if (!tag.selfClosing) {
|
|
@@ -29,7 +24,6 @@ function walkSource(source, registry, sourceFile, chain, occurrences) {
|
|
|
29
24
|
children = source.slice(tag.end, close.contentEnd);
|
|
30
25
|
replaceEnd = close.tagEnd;
|
|
31
26
|
}
|
|
32
|
-
|
|
33
27
|
const compPath = registry.get(tag.name);
|
|
34
28
|
if (!compPath) {
|
|
35
29
|
throw new Error(`Unknown component "${tag.name}" referenced in ${sourceFile}`);
|
|
@@ -38,47 +32,35 @@ function walkSource(source, registry, sourceFile, chain, occurrences) {
|
|
|
38
32
|
const cycle = [...chain, tag.name].join(' -> ');
|
|
39
33
|
throw new Error(`Circular component dependency detected: ${cycle}\nFile: ${sourceFile}`);
|
|
40
34
|
}
|
|
41
|
-
|
|
42
35
|
occurrences.push({
|
|
43
36
|
name: tag.name,
|
|
44
37
|
attrs: String(tag.attrs || '').trim(),
|
|
45
38
|
ownerPath: sourceFile,
|
|
46
39
|
componentPath: compPath
|
|
47
40
|
});
|
|
48
|
-
|
|
49
41
|
const compSource = readFileSync(compPath, 'utf8');
|
|
50
42
|
const nextTemplate = materializeTemplate(compSource, tag.name, children, compPath);
|
|
51
43
|
walkSource(nextTemplate, registry, compPath, [...chain, tag.name], occurrences);
|
|
52
44
|
cursor = replaceEnd;
|
|
53
45
|
}
|
|
54
46
|
}
|
|
55
|
-
|
|
56
47
|
function materializeTemplate(componentSource, name, children, componentPath) {
|
|
57
48
|
let template = extractTemplate(componentSource);
|
|
58
49
|
const slotCount = countSlots(template);
|
|
59
|
-
|
|
60
50
|
if (isDocumentMode(template)) {
|
|
61
51
|
if (slotCount !== 1) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Document Mode component "${name}" must contain exactly one <slot />, found ${slotCount}.\nFile: ${componentPath}`
|
|
64
|
-
);
|
|
52
|
+
throw new Error(`Document Mode component "${name}" must contain exactly one <slot />, found ${slotCount}.\nFile: ${componentPath}`);
|
|
65
53
|
}
|
|
66
54
|
return replaceSlot(template, children);
|
|
67
55
|
}
|
|
68
|
-
|
|
69
56
|
if (children.trim().length > 0 && slotCount === 0) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Component "${name}" has children but its template has no <slot />.\nEither add <slot /> to ${componentPath} or make the tag self-closing.`
|
|
72
|
-
);
|
|
57
|
+
throw new Error(`Component "${name}" has children but its template has no <slot />.\nEither add <slot /> to ${componentPath} or make the tag self-closing.`);
|
|
73
58
|
}
|
|
74
|
-
|
|
75
59
|
if (slotCount > 0) {
|
|
76
60
|
template = replaceSlot(template, children || '');
|
|
77
61
|
}
|
|
78
|
-
|
|
79
62
|
return template;
|
|
80
63
|
}
|
|
81
|
-
|
|
82
64
|
function findNextKnownTag(source, registry, startIndex) {
|
|
83
65
|
OPEN_COMPONENT_TAG_RE.lastIndex = startIndex;
|
|
84
66
|
let match;
|
|
@@ -100,25 +82,23 @@ function findNextKnownTag(source, registry, startIndex) {
|
|
|
100
82
|
}
|
|
101
83
|
return null;
|
|
102
84
|
}
|
|
103
|
-
|
|
104
85
|
function isInsideExpressionScope(source, index) {
|
|
105
86
|
let depth = 0;
|
|
106
87
|
for (let i = 0; i < index; i++) {
|
|
107
88
|
if (source[i] === '{') {
|
|
108
89
|
depth += 1;
|
|
109
|
-
}
|
|
90
|
+
}
|
|
91
|
+
else if (source[i] === '}') {
|
|
110
92
|
depth = Math.max(0, depth - 1);
|
|
111
93
|
}
|
|
112
94
|
}
|
|
113
95
|
return depth > 0;
|
|
114
96
|
}
|
|
115
|
-
|
|
116
97
|
function findMatchingClose(source, tagName, startAfterOpen) {
|
|
117
98
|
let depth = 1;
|
|
118
99
|
const escapedName = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
119
100
|
const tagRe = new RegExp(`<(/?)${escapedName}(?:\\s[^<>]*?)?\\s*(/?)>`, 'g');
|
|
120
101
|
tagRe.lastIndex = startAfterOpen;
|
|
121
|
-
|
|
122
102
|
let match;
|
|
123
103
|
while ((match = tagRe.exec(source)) !== null) {
|
|
124
104
|
const isClose = match[1] === '/';
|
|
@@ -134,19 +114,17 @@ function findMatchingClose(source, tagName, startAfterOpen) {
|
|
|
134
114
|
tagEnd: match.index + match[0].length
|
|
135
115
|
};
|
|
136
116
|
}
|
|
137
|
-
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
138
119
|
depth += 1;
|
|
139
120
|
}
|
|
140
121
|
}
|
|
141
|
-
|
|
142
122
|
return null;
|
|
143
123
|
}
|
|
144
|
-
|
|
145
124
|
function countSlots(template) {
|
|
146
125
|
const matches = template.match(/<slot\s*>\s*<\/slot>|<slot\s*\/>|<slot\s*>/gi);
|
|
147
126
|
return matches ? matches.length : 0;
|
|
148
127
|
}
|
|
149
|
-
|
|
150
128
|
function replaceSlot(template, content) {
|
|
151
129
|
return template.replace(/<slot\s*>\s*<\/slot>|<slot\s*\/>|<slot\s*>/i, content);
|
|
152
130
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create and start a development server.
|
|
3
|
+
*
|
|
4
|
+
* @param {{ pagesDir: string, outDir: string, port?: number, host?: string, config?: object, logger?: object | null }} options
|
|
5
|
+
* @returns {Promise<{ server: import('http').Server, port: number, close: () => void }>}
|
|
6
|
+
*/
|
|
7
|
+
export function createDevServer(options: {
|
|
8
|
+
pagesDir: string;
|
|
9
|
+
outDir: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
host?: string;
|
|
12
|
+
config?: object;
|
|
13
|
+
logger?: object | null;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
server: import("http").Server;
|
|
16
|
+
port: number;
|
|
17
|
+
close: () => void;
|
|
18
|
+
}>;
|