@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,372 @@
1
+ import { performance } from 'node:perf_hooks';
2
+ import { extractTemplate } from '../resolve-components.js';
3
+ import { runCompiler } from './compiler-runtime.js';
4
+ /**
5
+ * @param {string} compPath
6
+ * @param {string} componentSource
7
+ * @param {object} compIr
8
+ * @param {object} compilerOpts
9
+ * @param {string|object} compilerBin
10
+ * @param {Map<string, string[]> | null} [templateExpressionCache]
11
+ * @param {Record<string, number> | null} [rewriteMetrics]
12
+ * @returns {{
13
+ * map: Map<string, string>,
14
+ * bindings: Map<string, {
15
+ * compiled_expr: string | null,
16
+ * signal_index: number | null,
17
+ * signal_indices: number[],
18
+ * state_index: number | null,
19
+ * component_instance: string | null,
20
+ * component_binding: string | null
21
+ * }>,
22
+ * signals: Array<{ id?: number, kind?: string, state_index?: number }>,
23
+ * stateBindings: Array<{ key?: string, value?: string }>,
24
+ * ambiguous: Set<string>,
25
+ * sequence: Array<{ raw: string, rewritten: string, binding: object | null }>
26
+ * }}
27
+ */
28
+ export function buildComponentExpressionRewrite(compPath, componentSource, compIr, compilerOpts, compilerBin, templateExpressionCache = null, rewriteMetrics = null) {
29
+ const out = {
30
+ map: new Map(),
31
+ bindings: new Map(),
32
+ signals: Array.isArray(compIr?.signals) ? compIr.signals : [],
33
+ stateBindings: Array.isArray(compIr?.hoisted?.state) ? compIr.hoisted.state : [],
34
+ ambiguous: new Set(),
35
+ sequence: []
36
+ };
37
+ const rewrittenExpressions = Array.isArray(compIr?.expressions) ? compIr.expressions : [];
38
+ const rewrittenBindings = Array.isArray(compIr?.expression_bindings) ? compIr.expression_bindings : [];
39
+ if (rewrittenExpressions.length === 0) {
40
+ return out;
41
+ }
42
+ const hoistedState = Array.isArray(compIr?.hoisted?.state) ? compIr.hoisted.state : [];
43
+ const hoistedFunctions = Array.isArray(compIr?.hoisted?.functions) ? compIr.hoisted.functions : [];
44
+ const hoistedDeclarations = Array.isArray(compIr?.hoisted?.declarations) ? compIr.hoisted.declarations : [];
45
+ const signals = Array.isArray(compIr?.signals) ? compIr.signals : [];
46
+ if (hoistedState.length === 0 &&
47
+ hoistedFunctions.length === 0 &&
48
+ hoistedDeclarations.length === 0 &&
49
+ signals.length === 0) {
50
+ return out;
51
+ }
52
+ if (rewriteMetrics && typeof rewriteMetrics === 'object') {
53
+ rewriteMetrics.calls += 1;
54
+ }
55
+ const templateOnly = extractTemplate(componentSource);
56
+ if (!templateOnly.trim()) {
57
+ return out;
58
+ }
59
+ const cacheKey = `${compPath}\u0000${templateOnly}`;
60
+ let rawExpressions = null;
61
+ if (templateExpressionCache instanceof Map && templateExpressionCache.has(cacheKey)) {
62
+ rawExpressions = templateExpressionCache.get(cacheKey);
63
+ if (rewriteMetrics && typeof rewriteMetrics === 'object') {
64
+ rewriteMetrics.cacheHits += 1;
65
+ }
66
+ }
67
+ else {
68
+ let templateIr;
69
+ const templateCompileStartedAt = performance.now();
70
+ try {
71
+ templateIr = runCompiler(compPath, templateOnly, compilerOpts, {
72
+ suppressWarnings: true,
73
+ compilerToolchain: compilerBin
74
+ });
75
+ }
76
+ catch {
77
+ return out;
78
+ }
79
+ rawExpressions = Array.isArray(templateIr?.expressions) ? templateIr.expressions : [];
80
+ if (templateExpressionCache instanceof Map) {
81
+ templateExpressionCache.set(cacheKey, rawExpressions);
82
+ }
83
+ if (rewriteMetrics && typeof rewriteMetrics === 'object') {
84
+ rewriteMetrics.cacheMisses += 1;
85
+ rewriteMetrics.templateCompileMs += Math.round((performance.now() - templateCompileStartedAt) * 100) / 100;
86
+ }
87
+ }
88
+ const count = Math.min(rawExpressions.length, rewrittenExpressions.length);
89
+ for (let i = 0; i < count; i++) {
90
+ const raw = rawExpressions[i];
91
+ const rewritten = rewrittenExpressions[i];
92
+ if (typeof raw !== 'string' || typeof rewritten !== 'string') {
93
+ continue;
94
+ }
95
+ const binding = rewrittenBindings[i];
96
+ const normalizedBinding = binding && typeof binding === 'object'
97
+ ? {
98
+ compiled_expr: typeof binding.compiled_expr === 'string' ? binding.compiled_expr : null,
99
+ signal_index: Number.isInteger(binding.signal_index) ? binding.signal_index : null,
100
+ signal_indices: Array.isArray(binding.signal_indices)
101
+ ? binding.signal_indices.filter((value) => Number.isInteger(value))
102
+ : [],
103
+ state_index: Number.isInteger(binding.state_index) ? binding.state_index : null,
104
+ component_instance: typeof binding.component_instance === 'string' ? binding.component_instance : null,
105
+ component_binding: typeof binding.component_binding === 'string' ? binding.component_binding : null
106
+ }
107
+ : null;
108
+ out.sequence.push({ raw, rewritten, binding: normalizedBinding });
109
+ if (!out.ambiguous.has(raw) && normalizedBinding) {
110
+ const existingBinding = out.bindings.get(raw);
111
+ if (existingBinding) {
112
+ if (JSON.stringify(existingBinding) !== JSON.stringify(normalizedBinding)) {
113
+ out.bindings.delete(raw);
114
+ out.map.delete(raw);
115
+ out.ambiguous.add(raw);
116
+ continue;
117
+ }
118
+ }
119
+ else {
120
+ out.bindings.set(raw, normalizedBinding);
121
+ }
122
+ }
123
+ if (raw !== rewritten) {
124
+ const existing = out.map.get(raw);
125
+ if (existing && existing !== rewritten) {
126
+ out.bindings.delete(raw);
127
+ out.map.delete(raw);
128
+ out.ambiguous.add(raw);
129
+ continue;
130
+ }
131
+ if (!out.ambiguous.has(raw)) {
132
+ out.map.set(raw, rewritten);
133
+ }
134
+ }
135
+ }
136
+ return out;
137
+ }
138
+ /**
139
+ * @param {string} compiledExpr
140
+ * @param {Array<{ state_index?: number }>} componentSignals
141
+ * @param {Array<{ key?: string }>} componentStateBindings
142
+ * @param {Map<string, number>} pageSignalIndexByStateKey
143
+ * @returns {string | null}
144
+ */
145
+ export function remapCompiledExpressionSignals(compiledExpr, componentSignals, componentStateBindings, pageSignalIndexByStateKey) {
146
+ if (typeof compiledExpr !== 'string' || compiledExpr.length === 0) {
147
+ return null;
148
+ }
149
+ return compiledExpr.replace(/signalMap\.get\((\d+)\)/g, (full, rawIndex) => {
150
+ const localIndex = Number.parseInt(rawIndex, 10);
151
+ if (!Number.isInteger(localIndex)) {
152
+ return full;
153
+ }
154
+ const signal = componentSignals[localIndex];
155
+ if (!signal || !Number.isInteger(signal.state_index)) {
156
+ return full;
157
+ }
158
+ const stateKey = componentStateBindings[signal.state_index]?.key;
159
+ if (typeof stateKey !== 'string' || stateKey.length === 0) {
160
+ return full;
161
+ }
162
+ const pageIndex = pageSignalIndexByStateKey.get(stateKey);
163
+ if (!Number.isInteger(pageIndex)) {
164
+ return full;
165
+ }
166
+ return `signalMap.get(${pageIndex})`;
167
+ });
168
+ }
169
+ /**
170
+ * @param {object} pageBindingContext
171
+ * @param {object} componentRewrite
172
+ * @param {object} binding
173
+ * @param {Record<string, number> | null} [resolutionMetrics]
174
+ * @returns {object | null}
175
+ */
176
+ export function resolveRewrittenBindingMetadata(pageBindingContext, componentRewrite, binding, resolutionMetrics = null) {
177
+ if (!binding || typeof binding !== 'object') {
178
+ return null;
179
+ }
180
+ let pageStateBindings;
181
+ let pageSignals;
182
+ let pageStateIndexByKey;
183
+ let pageSignalIndexByStateKey;
184
+ let pageSignalIndicesByStateIndex;
185
+ if (pageBindingContext &&
186
+ typeof pageBindingContext === 'object' &&
187
+ pageBindingContext.stateIndexByKey instanceof Map &&
188
+ pageBindingContext.signalIndexByStateKey instanceof Map) {
189
+ pageStateBindings = Array.isArray(pageBindingContext.stateEntries) ? pageBindingContext.stateEntries : [];
190
+ pageSignals = Array.isArray(pageBindingContext.signals) ? pageBindingContext.signals : [];
191
+ pageStateIndexByKey = pageBindingContext.stateIndexByKey;
192
+ pageSignalIndexByStateKey = pageBindingContext.signalIndexByStateKey;
193
+ pageSignalIndicesByStateIndex = pageBindingContext.signalIndicesByStateIndex instanceof Map
194
+ ? pageBindingContext.signalIndicesByStateIndex
195
+ : null;
196
+ }
197
+ else {
198
+ const mapConstructionStartedAt = performance.now();
199
+ pageStateBindings = Array.isArray(pageBindingContext?.hoisted?.state) ? pageBindingContext.hoisted.state : [];
200
+ pageSignals = Array.isArray(pageBindingContext?.signals) ? pageBindingContext.signals : [];
201
+ pageStateIndexByKey = new Map();
202
+ pageSignalIndexByStateKey = new Map();
203
+ pageSignalIndicesByStateIndex = new Map();
204
+ for (let index = 0; index < pageStateBindings.length; index++) {
205
+ const key = pageStateBindings[index]?.key;
206
+ if (typeof key === 'string' && key.length > 0 && !pageStateIndexByKey.has(key)) {
207
+ pageStateIndexByKey.set(key, index);
208
+ }
209
+ }
210
+ for (let index = 0; index < pageSignals.length; index++) {
211
+ const stateIndex = pageSignals[index]?.state_index;
212
+ if (!Number.isInteger(stateIndex) || stateIndex < 0) {
213
+ continue;
214
+ }
215
+ const stateKey = pageStateBindings[stateIndex]?.key;
216
+ if (typeof stateKey === 'string' && stateKey.length > 0 && !pageSignalIndexByStateKey.has(stateKey)) {
217
+ pageSignalIndexByStateKey.set(stateKey, index);
218
+ }
219
+ const existing = pageSignalIndicesByStateIndex.get(stateIndex);
220
+ if (existing) {
221
+ existing.push(index);
222
+ }
223
+ else {
224
+ pageSignalIndicesByStateIndex.set(stateIndex, [index]);
225
+ }
226
+ }
227
+ if (resolutionMetrics && typeof resolutionMetrics === 'object') {
228
+ resolutionMetrics.pageMapConstructionMs = (resolutionMetrics.pageMapConstructionMs || 0)
229
+ + (performance.now() - mapConstructionStartedAt);
230
+ }
231
+ }
232
+ const componentSignals = Array.isArray(componentRewrite?.signals) ? componentRewrite.signals : [];
233
+ const componentStateBindings = Array.isArray(componentRewrite?.stateBindings) ? componentRewrite.stateBindings : [];
234
+ const next = {
235
+ compiled_expr: typeof binding.compiled_expr === 'string' ? binding.compiled_expr : null,
236
+ signal_index: null,
237
+ signal_indices: [],
238
+ state_index: null,
239
+ component_instance: typeof binding.component_instance === 'string' ? binding.component_instance : null,
240
+ component_binding: typeof binding.component_binding === 'string' ? binding.component_binding : null
241
+ };
242
+ if (typeof next.compiled_expr === 'string' && next.compiled_expr.includes('signalMap.get(')) {
243
+ const remapStartedAt = performance.now();
244
+ const remapped = remapCompiledExpressionSignals(next.compiled_expr, componentSignals, componentStateBindings, pageSignalIndexByStateKey);
245
+ if (remapped && remapped !== next.compiled_expr) {
246
+ next.compiled_expr = remapped;
247
+ }
248
+ if (resolutionMetrics && typeof resolutionMetrics === 'object') {
249
+ resolutionMetrics.compiledSignalRemapMs = (resolutionMetrics.compiledSignalRemapMs || 0)
250
+ + (performance.now() - remapStartedAt);
251
+ }
252
+ }
253
+ const componentStateIndex = Number.isInteger(binding.state_index) ? binding.state_index : null;
254
+ const componentStateKey = componentStateIndex !== null
255
+ ? componentStateBindings[componentStateIndex]?.key
256
+ : null;
257
+ if (typeof componentStateKey === 'string' && componentStateKey.length > 0) {
258
+ const lookupStartedAt = performance.now();
259
+ const pageStateIndex = pageStateIndexByKey.get(componentStateKey);
260
+ if (Number.isInteger(pageStateIndex)) {
261
+ next.state_index = pageStateIndex;
262
+ const pageSignalIndices = pageSignalIndicesByStateIndex?.get(pageStateIndex) || [];
263
+ next.signal_indices = [...pageSignalIndices];
264
+ if (pageSignalIndices.length === 1) {
265
+ next.signal_index = pageSignalIndices[0];
266
+ }
267
+ }
268
+ if (resolutionMetrics && typeof resolutionMetrics === 'object') {
269
+ resolutionMetrics.fallbackSignalStateLookupMs = (resolutionMetrics.fallbackSignalStateLookupMs || 0)
270
+ + (performance.now() - lookupStartedAt);
271
+ }
272
+ }
273
+ if (!Number.isInteger(next.signal_index) && Array.isArray(binding.signal_indices)) {
274
+ const remappedSignalIndices = [];
275
+ for (const signalIndex of binding.signal_indices) {
276
+ if (!Number.isInteger(signalIndex)) {
277
+ continue;
278
+ }
279
+ const signal = componentSignals[signalIndex];
280
+ if (!signal || !Number.isInteger(signal.state_index)) {
281
+ continue;
282
+ }
283
+ const stateKey = componentStateBindings[signal.state_index]?.key;
284
+ if (typeof stateKey !== 'string' || stateKey.length === 0) {
285
+ continue;
286
+ }
287
+ const pageSignalIndex = pageSignalIndexByStateKey.get(stateKey);
288
+ if (Number.isInteger(pageSignalIndex)) {
289
+ remappedSignalIndices.push(pageSignalIndex);
290
+ }
291
+ }
292
+ if (remappedSignalIndices.length > 0) {
293
+ next.signal_indices = [...new Set(remappedSignalIndices)].sort((a, b) => a - b);
294
+ if (next.signal_indices.length === 1) {
295
+ next.signal_index = next.signal_indices[0];
296
+ }
297
+ }
298
+ }
299
+ return next;
300
+ }
301
+ /**
302
+ * @param {Map<string, string>} pageMap
303
+ * @param {Map<string, object>} pageBindingMap
304
+ * @param {Set<string>} pageAmbiguous
305
+ * @param {object} componentRewrite
306
+ * @param {object} pageBindingContext
307
+ * @param {Record<string, number> | null} [bindingResolutionMetrics]
308
+ */
309
+ export function mergeExpressionRewriteMaps(pageMap, pageBindingMap, pageAmbiguous, componentRewrite, pageBindingContext, bindingResolutionMetrics = null) {
310
+ for (const raw of componentRewrite.ambiguous) {
311
+ pageAmbiguous.add(raw);
312
+ pageMap.delete(raw);
313
+ pageBindingMap.delete(raw);
314
+ }
315
+ for (const [raw, binding] of componentRewrite.bindings.entries()) {
316
+ if (pageAmbiguous.has(raw)) {
317
+ continue;
318
+ }
319
+ const resolved = resolveRewrittenBindingMetadata(pageBindingContext, componentRewrite, binding, bindingResolutionMetrics);
320
+ const existing = pageBindingMap.get(raw);
321
+ if (existing && JSON.stringify(existing) !== JSON.stringify(resolved)) {
322
+ pageAmbiguous.add(raw);
323
+ pageMap.delete(raw);
324
+ pageBindingMap.delete(raw);
325
+ continue;
326
+ }
327
+ pageBindingMap.set(raw, resolved);
328
+ }
329
+ for (const [raw, rewritten] of componentRewrite.map.entries()) {
330
+ if (pageAmbiguous.has(raw)) {
331
+ continue;
332
+ }
333
+ const existing = pageMap.get(raw);
334
+ if (existing && existing !== rewritten) {
335
+ pageAmbiguous.add(raw);
336
+ pageMap.delete(raw);
337
+ pageBindingMap.delete(raw);
338
+ continue;
339
+ }
340
+ pageMap.set(raw, rewritten);
341
+ }
342
+ }
343
+ /**
344
+ * @param {string} identifier
345
+ * @param {Array<{ key?: string }>} stateBindings
346
+ * @param {Set<string> | null} [preferredKeys]
347
+ * @returns {string | null}
348
+ */
349
+ export function resolveStateKeyFromBindings(identifier, stateBindings, preferredKeys = null) {
350
+ const ident = String(identifier || '').trim();
351
+ if (!ident) {
352
+ return null;
353
+ }
354
+ const exact = stateBindings.find((entry) => String(entry?.key || '') === ident);
355
+ if (exact && typeof exact.key === 'string') {
356
+ return exact.key;
357
+ }
358
+ const suffix = `_${ident}`;
359
+ const matches = stateBindings
360
+ .map((entry) => String(entry?.key || ''))
361
+ .filter((key) => key.endsWith(suffix));
362
+ if (preferredKeys instanceof Set && preferredKeys.size > 0) {
363
+ const preferredMatches = matches.filter((key) => preferredKeys.has(key));
364
+ if (preferredMatches.length === 1) {
365
+ return preferredMatches[0];
366
+ }
367
+ }
368
+ if (matches.length === 1) {
369
+ return matches[0];
370
+ }
371
+ return null;
372
+ }
@@ -0,0 +1,44 @@
1
+ export function rewriteStaticImportLine(line: any, fromFile: any, toFile: any): any;
2
+ /**
3
+ * @param {string} line
4
+ * @returns {string | null}
5
+ */
6
+ export function extractStaticImportSpecifier(line: string): string | null;
7
+ /**
8
+ * @param {string} spec
9
+ * @returns {boolean}
10
+ */
11
+ export function isCssSpecifier(spec: string): boolean;
12
+ /**
13
+ * @param {string} source
14
+ * @param {string} fromFile
15
+ * @param {string} toFile
16
+ * @returns {string}
17
+ */
18
+ export function rewriteStaticImportsInSource(source: string, fromFile: string, toFile: string): string;
19
+ /**
20
+ * @param {string} source
21
+ * @param {string} sourceFile
22
+ * @param {object | null} [transformCache]
23
+ * @param {Record<string, number> | null} [mergeMetrics]
24
+ * @returns {string}
25
+ */
26
+ export function transpileTypeScriptToJs(source: string, sourceFile: string, transformCache?: object | null, mergeMetrics?: Record<string, number> | null): string;
27
+ /**
28
+ * @param {string} source
29
+ * @param {Set<string>} seenStaticImports
30
+ * @returns {string}
31
+ */
32
+ export function dedupeStaticImportsInSource(source: string, seenStaticImports: Set<string>): string;
33
+ /**
34
+ * @param {string} source
35
+ * @returns {string}
36
+ */
37
+ export function stripNonCssStaticImportsInSource(source: string): string;
38
+ /**
39
+ * @param {string} source
40
+ * @param {object | null} [transformCache]
41
+ * @param {Record<string, number> | null} [mergeMetrics]
42
+ * @returns {string}
43
+ */
44
+ export function deferComponentRuntimeBlock(source: string, transformCache?: object | null, mergeMetrics?: Record<string, number> | null): string;