@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.
Files changed (43) hide show
  1. package/dist/build.d.ts +32 -0
  2. package/dist/build.js +193 -548
  3. package/dist/compiler-bridge-runner.d.ts +5 -0
  4. package/dist/compiler-bridge-runner.js +70 -0
  5. package/dist/component-instance-ir.d.ts +6 -0
  6. package/dist/component-instance-ir.js +0 -20
  7. package/dist/component-occurrences.d.ts +6 -0
  8. package/dist/component-occurrences.js +6 -28
  9. package/dist/dev-server.d.ts +18 -0
  10. package/dist/dev-server.js +65 -114
  11. package/dist/dev-watch.d.ts +1 -0
  12. package/dist/dev-watch.js +2 -2
  13. package/dist/index.d.ts +8 -0
  14. package/dist/index.js +6 -28
  15. package/dist/manifest.d.ts +23 -0
  16. package/dist/manifest.js +22 -48
  17. package/dist/preview.d.ts +100 -0
  18. package/dist/preview.js +418 -488
  19. package/dist/resolve-components.d.ts +39 -0
  20. package/dist/resolve-components.js +30 -104
  21. package/dist/server/resolve-request-route.d.ts +39 -0
  22. package/dist/server/resolve-request-route.js +104 -113
  23. package/dist/server-contract.d.ts +39 -0
  24. package/dist/server-contract.js +15 -67
  25. package/dist/toolchain-paths.d.ts +23 -0
  26. package/dist/toolchain-paths.js +139 -39
  27. package/dist/toolchain-runner.d.ts +33 -0
  28. package/dist/toolchain-runner.js +194 -0
  29. package/dist/types/generate-env-dts.d.ts +5 -0
  30. package/dist/types/generate-env-dts.js +4 -2
  31. package/dist/types/generate-routes-dts.d.ts +8 -0
  32. package/dist/types/generate-routes-dts.js +7 -5
  33. package/dist/types/index.d.ts +14 -0
  34. package/dist/types/index.js +16 -7
  35. package/dist/ui/env.d.ts +18 -0
  36. package/dist/ui/env.js +0 -12
  37. package/dist/ui/format.d.ts +33 -0
  38. package/dist/ui/format.js +8 -46
  39. package/dist/ui/logger.d.ts +59 -0
  40. package/dist/ui/logger.js +3 -32
  41. package/dist/version-check.d.ts +54 -0
  42. package/dist/version-check.js +41 -98
  43. package/package.json +6 -4
@@ -0,0 +1,5 @@
1
+ export type BridgeArgs = {
2
+ bridgeModule: string;
3
+ filePath: string;
4
+ stdin: boolean;
5
+ };
@@ -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') {
@@ -0,0 +1,6 @@
1
+ export function collectExpandedComponentOccurrences(source: any, registry: any, sourceFile: any): {
2
+ name: string;
3
+ attrs: string;
4
+ ownerPath: string;
5
+ componentPath: string;
6
+ }[];
@@ -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
- } else if (source[i] === '}') {
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
- } else {
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
+ }>;