@jay-framework/compiler-jay-html 0.8.0 → 0.9.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.
package/dist/index.js CHANGED
@@ -4,6 +4,389 @@ import fs from "fs/promises";
4
4
  import { analyzeExportedTypes } from "@jay-framework/compiler-analyze-exported-types";
5
5
  import fs$1 from "fs";
6
6
  import { createRequire } from "module";
7
+ var ContractTagType = /* @__PURE__ */ ((ContractTagType2) => {
8
+ ContractTagType2[ContractTagType2["data"] = 0] = "data";
9
+ ContractTagType2[ContractTagType2["interactive"] = 1] = "interactive";
10
+ ContractTagType2[ContractTagType2["variant"] = 2] = "variant";
11
+ ContractTagType2[ContractTagType2["subContract"] = 3] = "subContract";
12
+ return ContractTagType2;
13
+ })(ContractTagType || {});
14
+ const PHASE_ORDER = {
15
+ slow: 0,
16
+ fast: 1,
17
+ "fast+interactive": 2
18
+ };
19
+ const DEFAULT_PHASE = "slow";
20
+ function getEffectivePhase(tag, parentPhase) {
21
+ if (tag.type.includes(ContractTagType.interactive)) {
22
+ return "fast+interactive";
23
+ }
24
+ if (tag.phase) {
25
+ return tag.phase;
26
+ }
27
+ if (parentPhase) {
28
+ return parentPhase;
29
+ }
30
+ return DEFAULT_PHASE;
31
+ }
32
+ function isPhaseCompatible(childPhase, parentPhase) {
33
+ return PHASE_ORDER[childPhase] >= PHASE_ORDER[parentPhase];
34
+ }
35
+ function isTagInPhase(tag, targetPhase, parentPhase) {
36
+ if (tag.type.includes(ContractTagType.interactive) && !tag.dataType) {
37
+ return false;
38
+ }
39
+ const effectivePhase = getEffectivePhase(tag, parentPhase);
40
+ return effectivePhase === targetPhase;
41
+ }
42
+ function validateTagPhases(tag, parentPhase, tagPath = "") {
43
+ const validations = [];
44
+ const currentPath = tagPath ? `${tagPath}.${tag.tag}` : tag.tag;
45
+ const effectivePhase = getEffectivePhase(tag, parentPhase);
46
+ if (parentPhase && !isPhaseCompatible(effectivePhase, parentPhase)) {
47
+ validations.push(
48
+ `Tag [${currentPath}] has phase [${effectivePhase}] which is earlier than parent phase [${parentPhase}]. Child phases must be same or later than parent (slow < fast < fast+interactive)`
49
+ );
50
+ }
51
+ if (tag.type.includes(ContractTagType.subContract) && tag.tags) {
52
+ if (tag.repeated) {
53
+ tag.tags.forEach((childTag) => {
54
+ const childValidations = validateTagPhases(childTag, effectivePhase, currentPath);
55
+ validations.push(...childValidations);
56
+ });
57
+ } else {
58
+ tag.tags.forEach((childTag) => {
59
+ const childValidations = validateTagPhases(childTag, void 0, currentPath);
60
+ validations.push(...childValidations);
61
+ });
62
+ }
63
+ }
64
+ return validations;
65
+ }
66
+ function validateContractPhases(contract) {
67
+ const validations = [];
68
+ contract.tags.forEach((tag) => {
69
+ const tagValidations = validateTagPhases(tag);
70
+ validations.push(...tagValidations);
71
+ });
72
+ return validations;
73
+ }
74
+ function filterTagsByPhase(tags, targetPhase, parentPhase) {
75
+ const filteredTags = [];
76
+ for (const tag of tags) {
77
+ if (!isTagInPhase(tag, targetPhase, parentPhase)) {
78
+ continue;
79
+ }
80
+ const effectivePhase = getEffectivePhase(tag, parentPhase);
81
+ if (tag.type.includes(ContractTagType.subContract) && tag.tags) {
82
+ const filteredNestedTags = filterTagsByPhase(tag.tags, targetPhase, effectivePhase);
83
+ if (filteredNestedTags.length > 0) {
84
+ filteredTags.push({
85
+ ...tag,
86
+ tags: filteredNestedTags
87
+ });
88
+ }
89
+ } else {
90
+ filteredTags.push(tag);
91
+ }
92
+ }
93
+ return filteredTags;
94
+ }
95
+ function createPhaseContract(contract, targetPhase) {
96
+ return {
97
+ ...contract,
98
+ tags: filterTagsByPhase(contract.tags, targetPhase)
99
+ };
100
+ }
101
+ var __assign$3 = function() {
102
+ __assign$3 = Object.assign || function __assign2(t) {
103
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
104
+ s = arguments[i];
105
+ for (var p in s)
106
+ if (Object.prototype.hasOwnProperty.call(s, p))
107
+ t[p] = s[p];
108
+ }
109
+ return t;
110
+ };
111
+ return __assign$3.apply(this, arguments);
112
+ };
113
+ typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
114
+ var e2 = new Error(message);
115
+ return e2.name = "SuppressedError", e2.error = error, e2.suppressed = suppressed, e2;
116
+ };
117
+ function lowerCase(str2) {
118
+ return str2.toLowerCase();
119
+ }
120
+ var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
121
+ var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
122
+ function noCase(input, options) {
123
+ if (options === void 0) {
124
+ options = {};
125
+ }
126
+ var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
127
+ var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
128
+ var start = 0;
129
+ var end = result.length;
130
+ while (result.charAt(start) === "\0")
131
+ start++;
132
+ while (result.charAt(end - 1) === "\0")
133
+ end--;
134
+ return result.slice(start, end).split("\0").map(transform).join(delimiter);
135
+ }
136
+ function replace(input, re, value) {
137
+ if (re instanceof RegExp)
138
+ return input.replace(re, value);
139
+ return re.reduce(function(input2, re2) {
140
+ return input2.replace(re2, value);
141
+ }, input);
142
+ }
143
+ function pascalCaseTransform(input, index) {
144
+ var firstChar = input.charAt(0);
145
+ var lowerChars = input.substr(1).toLowerCase();
146
+ if (index > 0 && firstChar >= "0" && firstChar <= "9") {
147
+ return "_" + firstChar + lowerChars;
148
+ }
149
+ return "" + firstChar.toUpperCase() + lowerChars;
150
+ }
151
+ function pascalCase(input, options) {
152
+ if (options === void 0) {
153
+ options = {};
154
+ }
155
+ return noCase(input, __assign$3({ delimiter: "", transform: pascalCaseTransform }, options));
156
+ }
157
+ function camelCaseTransform(input, index) {
158
+ if (index === 0)
159
+ return input.toLowerCase();
160
+ return pascalCaseTransform(input, index);
161
+ }
162
+ function camelCase(input, options) {
163
+ if (options === void 0) {
164
+ options = {};
165
+ }
166
+ return pascalCase(input, __assign$3({ transform: camelCaseTransform }, options));
167
+ }
168
+ function upperCaseFirst(input) {
169
+ return input.charAt(0).toUpperCase() + input.substr(1);
170
+ }
171
+ function capitalCaseTransform(input) {
172
+ return upperCaseFirst(input.toLowerCase());
173
+ }
174
+ function capitalCase(input, options) {
175
+ if (options === void 0) {
176
+ options = {};
177
+ }
178
+ return noCase(input, __assign$3({ delimiter: " ", transform: capitalCaseTransform }, options));
179
+ }
180
+ function shouldIncludeInPhase(propertyPhase, targetPhase) {
181
+ if (targetPhase === "slow") {
182
+ return propertyPhase === "slow";
183
+ } else if (targetPhase === "fast") {
184
+ return propertyPhase === "fast" || propertyPhase === "fast+interactive";
185
+ } else if (targetPhase === "fast+interactive") {
186
+ return propertyPhase === "fast+interactive";
187
+ }
188
+ return false;
189
+ }
190
+ function extractPropertyPathsAndArrays(tags, targetPhase, parentPath = [], parentPhase) {
191
+ const paths = [];
192
+ const arrays = [];
193
+ const asyncProps = [];
194
+ for (const tag of tags) {
195
+ if (tag.type.includes(ContractTagType.interactive) && !tag.dataType) {
196
+ continue;
197
+ }
198
+ const effectivePhase = getEffectivePhase(tag, parentPhase);
199
+ const propertyName = camelCase(tag.tag);
200
+ const currentPath = [...parentPath, propertyName];
201
+ const isArray = tag.repeated || false;
202
+ const isAsync = tag.async || false;
203
+ if (tag.type.includes(ContractTagType.subContract) && tag.tags) {
204
+ const result = extractPropertyPathsAndArrays(
205
+ tag.tags,
206
+ targetPhase,
207
+ currentPath,
208
+ effectivePhase
209
+ );
210
+ if (result.paths.length > 0) {
211
+ paths.push(...result.paths);
212
+ arrays.push(...result.arrays);
213
+ asyncProps.push(...result.asyncProps);
214
+ if (isArray) {
215
+ arrays.push({ path: currentPath.join(".") });
216
+ }
217
+ if (isAsync) {
218
+ asyncProps.push({ path: currentPath.join(".") });
219
+ }
220
+ }
221
+ } else {
222
+ if (shouldIncludeInPhase(effectivePhase, targetPhase)) {
223
+ paths.push({
224
+ path: parentPath,
225
+ propertyName
226
+ });
227
+ }
228
+ }
229
+ }
230
+ return { paths, arrays, asyncProps };
231
+ }
232
+ function groupPathsByParent(paths) {
233
+ const grouped = /* @__PURE__ */ new Map();
234
+ for (const { path: path2, propertyName } of paths) {
235
+ const parentKey = path2.join(".");
236
+ if (!grouped.has(parentKey)) {
237
+ grouped.set(parentKey, []);
238
+ }
239
+ grouped.get(parentKey).push(propertyName);
240
+ }
241
+ return grouped;
242
+ }
243
+ function countTotalProperties(tags, targetPath, currentPath = []) {
244
+ let count = 0;
245
+ for (const tag of tags) {
246
+ if (tag.type.includes(ContractTagType.interactive) && !tag.dataType) {
247
+ continue;
248
+ }
249
+ const propertyName = camelCase(tag.tag);
250
+ const newPath = [...currentPath, propertyName];
251
+ const pathKey = newPath.join(".");
252
+ const targetKey = targetPath.join(".");
253
+ if (pathKey === targetKey && tag.type.includes(ContractTagType.subContract) && tag.tags) {
254
+ for (const childTag of tag.tags) {
255
+ if (childTag.type.includes(ContractTagType.interactive) && !childTag.dataType) {
256
+ continue;
257
+ }
258
+ count++;
259
+ }
260
+ return count;
261
+ }
262
+ if (tag.type.includes(ContractTagType.subContract) && tag.tags) {
263
+ const result = countTotalProperties(tag.tags, targetPath, newPath);
264
+ if (result > 0) {
265
+ return result;
266
+ }
267
+ }
268
+ }
269
+ return count;
270
+ }
271
+ function buildPickExpression(baseTypeName, pathGroups, arrays, asyncProps, contractTags, currentPath = []) {
272
+ const currentKey = currentPath.join(".");
273
+ const properties = pathGroups.get(currentKey) || [];
274
+ const childPropertyNames = /* @__PURE__ */ new Set();
275
+ for (const key of pathGroups.keys()) {
276
+ const prefix = currentKey ? currentKey + "." : "";
277
+ if (key.startsWith(prefix) && key !== currentKey) {
278
+ const remainingPath = key.slice(prefix.length);
279
+ const firstSegment = remainingPath.split(".")[0];
280
+ if (firstSegment) {
281
+ childPropertyNames.add(firstSegment);
282
+ }
283
+ }
284
+ }
285
+ const pickPart = [];
286
+ const nestedProperties = [];
287
+ const directProps = properties.filter((p) => !childPropertyNames.has(p));
288
+ if (directProps.length > 0) {
289
+ const pathAccess = currentPath.length > 0 ? `${baseTypeName}${currentPath.map((p) => `['${p}']`).join("")}` : baseTypeName;
290
+ pickPart.push(`Pick<${pathAccess}, ${directProps.map((p) => `'${p}'`).join(" | ")}>`);
291
+ }
292
+ for (const childName of childPropertyNames) {
293
+ const childPath = [...currentPath, childName];
294
+ const childPathKey = childPath.join(".");
295
+ const isArray = arrays.has(childPathKey);
296
+ const isAsync = asyncProps.has(childPathKey);
297
+ const childProperties = pathGroups.get(childPathKey) || [];
298
+ const totalProperties = countTotalProperties(contractTags, childPath);
299
+ const isPickingAllProperties = totalProperties > 0 && childProperties.length === totalProperties;
300
+ const childExpression = buildPickExpression(
301
+ baseTypeName,
302
+ pathGroups,
303
+ arrays,
304
+ asyncProps,
305
+ contractTags,
306
+ childPath
307
+ );
308
+ if (childExpression) {
309
+ let fullExpression;
310
+ const originalPathAccess = `${baseTypeName}${childPath.map((p) => `['${p}']`).join("")}`;
311
+ if (isPickingAllProperties && childExpression === `Pick<${originalPathAccess}, ${childProperties.map((p) => `'${p}'`).join(" | ")}>`) {
312
+ const directTypeRef = originalPathAccess;
313
+ if (isAsync) {
314
+ if (isArray) {
315
+ fullExpression = `Promise<Array<${directTypeRef}[number]>>`;
316
+ } else {
317
+ fullExpression = `Promise<${directTypeRef}>`;
318
+ }
319
+ } else if (isArray) {
320
+ fullExpression = `Array<${directTypeRef}[number]>`;
321
+ } else {
322
+ fullExpression = directTypeRef;
323
+ }
324
+ } else {
325
+ if (isAsync) {
326
+ if (isArray) {
327
+ const unwrappedArrayAccess = `Awaited<${originalPathAccess}>[number]`;
328
+ const unwrappedExpression = childExpression.replace(
329
+ originalPathAccess,
330
+ unwrappedArrayAccess
331
+ );
332
+ fullExpression = `Promise<Array<${unwrappedExpression}>>`;
333
+ } else {
334
+ const unwrappedAccess = `Awaited<${originalPathAccess}>`;
335
+ const unwrappedExpression = childExpression.replace(
336
+ originalPathAccess,
337
+ unwrappedAccess
338
+ );
339
+ fullExpression = `Promise<${unwrappedExpression}>`;
340
+ }
341
+ } else if (isArray) {
342
+ const arrayElementAccess = `${originalPathAccess}[number]`;
343
+ fullExpression = `Array<${childExpression.replace(originalPathAccess, arrayElementAccess)}>`;
344
+ } else {
345
+ fullExpression = childExpression;
346
+ }
347
+ }
348
+ nestedProperties.push(` ${childName}: ${fullExpression};`);
349
+ }
350
+ }
351
+ if (pickPart.length === 0 && nestedProperties.length === 0) {
352
+ return "{}";
353
+ } else if (pickPart.length === 0) {
354
+ return `{
355
+ ${nestedProperties.join("\n")}
356
+ }`;
357
+ } else if (nestedProperties.length === 0) {
358
+ return pickPart[0];
359
+ } else {
360
+ return `${pickPart[0]} & {
361
+ ${nestedProperties.join("\n")}
362
+ }`;
363
+ }
364
+ }
365
+ function generatePhaseViewStateType(contract, phase, baseTypeName) {
366
+ const phaseName = phase === "fast+interactive" ? "Interactive" : pascalCase(phase);
367
+ const typeName = `${pascalCase(contract.name)}${phaseName}ViewState`;
368
+ const { paths, arrays, asyncProps } = extractPropertyPathsAndArrays(contract.tags, phase);
369
+ if (paths.length === 0) {
370
+ return `export type ${typeName} = {};`;
371
+ }
372
+ const pathGroups = groupPathsByParent(paths);
373
+ const arraySet = new Set(arrays.map((a) => a.path));
374
+ const asyncSet = new Set(asyncProps.map((a) => a.path));
375
+ const pickExpression = buildPickExpression(
376
+ baseTypeName,
377
+ pathGroups,
378
+ arraySet,
379
+ asyncSet,
380
+ contract.tags
381
+ );
382
+ return `export type ${typeName} = ${pickExpression};`;
383
+ }
384
+ function generateAllPhaseViewStateTypes(contract, baseTypeName) {
385
+ const slowType = generatePhaseViewStateType(contract, "slow", baseTypeName);
386
+ const fastType = generatePhaseViewStateType(contract, "fast", baseTypeName);
387
+ const interactiveType = generatePhaseViewStateType(contract, "fast+interactive", baseTypeName);
388
+ return [slowType, fastType, interactiveType].join("\n\n");
389
+ }
7
390
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
8
391
  function getDefaultExportFromCjs(x) {
9
392
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -460,8 +843,8 @@ var __extends$2 = commonjsGlobal && commonjsGlobal.__extends || function() {
460
843
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
461
844
  };
462
845
  }();
463
- var __assign$3 = commonjsGlobal && commonjsGlobal.__assign || function() {
464
- __assign$3 = Object.assign || function(t) {
846
+ var __assign$2 = commonjsGlobal && commonjsGlobal.__assign || function() {
847
+ __assign$2 = Object.assign || function(t) {
465
848
  for (var s, i = 1, n = arguments.length; i < n; i++) {
466
849
  s = arguments[i];
467
850
  for (var p in s)
@@ -470,7 +853,7 @@ var __assign$3 = commonjsGlobal && commonjsGlobal.__assign || function() {
470
853
  }
471
854
  return t;
472
855
  };
473
- return __assign$3.apply(this, arguments);
856
+ return __assign$2.apply(this, arguments);
474
857
  };
475
858
  Object.defineProperty(node, "__esModule", { value: true });
476
859
  node.cloneNode = node.hasChildren = node.isDocument = node.isDirective = node.isComment = node.isText = node.isCDATA = node.isTag = node.Element = node.Document = node.CDATA = node.NodeWithChildren = node.ProcessingInstruction = node.Comment = node.Text = node.DataNode = node.Node = void 0;
@@ -809,7 +1192,7 @@ function cloneNode(node2, recursive) {
809
1192
  result = new Comment(node2.data);
810
1193
  } else if (isTag$1(node2)) {
811
1194
  var children = recursive ? cloneChildren(node2.children) : [];
812
- var clone_1 = new Element(node2.name, __assign$3({}, node2.attribs), children);
1195
+ var clone_1 = new Element(node2.name, __assign$2({}, node2.attribs), children);
813
1196
  children.forEach(function(child) {
814
1197
  return child.parent = clone_1;
815
1198
  });
@@ -817,10 +1200,10 @@ function cloneNode(node2, recursive) {
817
1200
  clone_1.namespace = node2.namespace;
818
1201
  }
819
1202
  if (node2["x-attribsNamespace"]) {
820
- clone_1["x-attribsNamespace"] = __assign$3({}, node2["x-attribsNamespace"]);
1203
+ clone_1["x-attribsNamespace"] = __assign$2({}, node2["x-attribsNamespace"]);
821
1204
  }
822
1205
  if (node2["x-attribsPrefix"]) {
823
- clone_1["x-attribsPrefix"] = __assign$3({}, node2["x-attribsPrefix"]);
1206
+ clone_1["x-attribsPrefix"] = __assign$2({}, node2["x-attribsPrefix"]);
824
1207
  }
825
1208
  result = clone_1;
826
1209
  } else if (isCDATA(node2)) {
@@ -1823,8 +2206,8 @@ foreignNames.attributeNames = new Map([
1823
2206
  ].map(function(val) {
1824
2207
  return [val.toLowerCase(), val];
1825
2208
  }));
1826
- var __assign$2 = commonjsGlobal && commonjsGlobal.__assign || function() {
1827
- __assign$2 = Object.assign || function(t) {
2209
+ var __assign$1 = commonjsGlobal && commonjsGlobal.__assign || function() {
2210
+ __assign$1 = Object.assign || function(t) {
1828
2211
  for (var s, i = 1, n = arguments.length; i < n; i++) {
1829
2212
  s = arguments[i];
1830
2213
  for (var p in s)
@@ -1833,7 +2216,7 @@ var __assign$2 = commonjsGlobal && commonjsGlobal.__assign || function() {
1833
2216
  }
1834
2217
  return t;
1835
2218
  };
1836
- return __assign$2.apply(this, arguments);
2219
+ return __assign$1.apply(this, arguments);
1837
2220
  };
1838
2221
  var __createBinding$1 = commonjsGlobal && commonjsGlobal.__createBinding || (Object.create ? function(o, m, k, k2) {
1839
2222
  if (k2 === void 0)
@@ -1972,11 +2355,11 @@ function renderTag(elem, opts) {
1972
2355
  if (opts.xmlMode === "foreign") {
1973
2356
  elem.name = (_a = foreignNames_js_1.elementNames.get(elem.name)) !== null && _a !== void 0 ? _a : elem.name;
1974
2357
  if (elem.parent && foreignModeIntegrationPoints.has(elem.parent.name)) {
1975
- opts = __assign$2(__assign$2({}, opts), { xmlMode: false });
2358
+ opts = __assign$1(__assign$1({}, opts), { xmlMode: false });
1976
2359
  }
1977
2360
  }
1978
2361
  if (!opts.xmlMode && foreignElements.has(elem.name)) {
1979
- opts = __assign$2(__assign$2({}, opts), { xmlMode: "foreign" });
2362
+ opts = __assign$1(__assign$1({}, opts), { xmlMode: "foreign" });
1980
2363
  }
1981
2364
  var tag = "<".concat(elem.name);
1982
2365
  var attribs = formatAttributes(elem.attribs, opts);
@@ -4709,8 +5092,8 @@ var __extends = commonjsGlobal && commonjsGlobal.__extends || function() {
4709
5092
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4710
5093
  };
4711
5094
  }();
4712
- var __assign$1 = commonjsGlobal && commonjsGlobal.__assign || function() {
4713
- __assign$1 = Object.assign || function(t) {
5095
+ var __assign = commonjsGlobal && commonjsGlobal.__assign || function() {
5096
+ __assign = Object.assign || function(t) {
4714
5097
  for (var s, i = 1, n = arguments.length; i < n; i++) {
4715
5098
  s = arguments[i];
4716
5099
  for (var p in s)
@@ -4719,7 +5102,7 @@ var __assign$1 = commonjsGlobal && commonjsGlobal.__assign || function() {
4719
5102
  }
4720
5103
  return t;
4721
5104
  };
4722
- return __assign$1.apply(this, arguments);
5105
+ return __assign.apply(this, arguments);
4723
5106
  };
4724
5107
  var __spreadArray = commonjsGlobal && commonjsGlobal.__spreadArray || function(to, from, pack) {
4725
5108
  if (pack || arguments.length === 2)
@@ -5048,7 +5431,7 @@ var HTMLElement = (
5048
5431
  if (content instanceof node_1$1.default) {
5049
5432
  content = [content];
5050
5433
  } else if (typeof content == "string") {
5051
- options = __assign$1(__assign$1({}, this._parseOptions), options);
5434
+ options = __assign(__assign({}, this._parseOptions), options);
5052
5435
  var r = parse$3(content, options);
5053
5436
  content = r.childNodes.length ? r.childNodes : [new text_1$1.default(r.innerHTML, this)];
5054
5437
  }
@@ -5247,7 +5630,7 @@ var HTMLElement = (
5247
5630
  while (el) {
5248
5631
  var e2 = (0, css_select_1.selectOne)(selector, el, {
5249
5632
  xmlMode: true,
5250
- adapter: __assign$1(__assign$1({}, matcher_1.default), { getChildren: function(node2) {
5633
+ adapter: __assign(__assign({}, matcher_1.default), { getChildren: function(node2) {
5251
5634
  var child = mapChild.get(node2);
5252
5635
  return child && [child];
5253
5636
  }, getSiblings: function(node2) {
@@ -10167,6 +10550,23 @@ class Variables {
10167
10550
  return variables;
10168
10551
  }
10169
10552
  }
10553
+ childVariableForWithData(accessor) {
10554
+ const path2 = accessor.terms.join(".");
10555
+ if (this.children[path2])
10556
+ return this.children[path2];
10557
+ else {
10558
+ let depth = 1;
10559
+ let parent = this;
10560
+ const maxDepth = 100;
10561
+ while (parent && parent.parent && depth < maxDepth) {
10562
+ depth++;
10563
+ parent = parent.parent;
10564
+ }
10565
+ const variables = new Variables(accessor.resolvedType, this, depth);
10566
+ this.children[path2] = variables;
10567
+ return variables;
10568
+ }
10569
+ }
10170
10570
  }
10171
10571
  function doParse(expression, startRule, vars) {
10172
10572
  try {
@@ -10255,73 +10655,6 @@ function parseIsEnum(expression) {
10255
10655
  function parseEnumValues(expression) {
10256
10656
  return doParse(expression, "enum");
10257
10657
  }
10258
- var __assign = function() {
10259
- __assign = Object.assign || function __assign2(t) {
10260
- for (var s, i = 1, n = arguments.length; i < n; i++) {
10261
- s = arguments[i];
10262
- for (var p in s)
10263
- if (Object.prototype.hasOwnProperty.call(s, p))
10264
- t[p] = s[p];
10265
- }
10266
- return t;
10267
- };
10268
- return __assign.apply(this, arguments);
10269
- };
10270
- typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
10271
- var e2 = new Error(message);
10272
- return e2.name = "SuppressedError", e2.error = error, e2.suppressed = suppressed, e2;
10273
- };
10274
- function lowerCase(str2) {
10275
- return str2.toLowerCase();
10276
- }
10277
- var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
10278
- var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
10279
- function noCase(input, options) {
10280
- if (options === void 0) {
10281
- options = {};
10282
- }
10283
- var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
10284
- var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
10285
- var start = 0;
10286
- var end = result.length;
10287
- while (result.charAt(start) === "\0")
10288
- start++;
10289
- while (result.charAt(end - 1) === "\0")
10290
- end--;
10291
- return result.slice(start, end).split("\0").map(transform).join(delimiter);
10292
- }
10293
- function replace(input, re, value) {
10294
- if (re instanceof RegExp)
10295
- return input.replace(re, value);
10296
- return re.reduce(function(input2, re2) {
10297
- return input2.replace(re2, value);
10298
- }, input);
10299
- }
10300
- function pascalCaseTransform(input, index) {
10301
- var firstChar = input.charAt(0);
10302
- var lowerChars = input.substr(1).toLowerCase();
10303
- if (index > 0 && firstChar >= "0" && firstChar <= "9") {
10304
- return "_" + firstChar + lowerChars;
10305
- }
10306
- return "" + firstChar.toUpperCase() + lowerChars;
10307
- }
10308
- function pascalCase(input, options) {
10309
- if (options === void 0) {
10310
- options = {};
10311
- }
10312
- return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
10313
- }
10314
- function camelCaseTransform(input, index) {
10315
- if (index === 0)
10316
- return input.toLowerCase();
10317
- return pascalCaseTransform(input, index);
10318
- }
10319
- function camelCase(input, options) {
10320
- if (options === void 0) {
10321
- options = {};
10322
- }
10323
- return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
10324
- }
10325
10658
  function isConditional(node2) {
10326
10659
  return node2.nodeType !== NodeType.TEXT_NODE && node2.hasAttribute("if");
10327
10660
  }
@@ -10442,7 +10775,8 @@ ${childType.values.map((_) => " " + _).join(",\n")}
10442
10775
  `Recursive type not resolved: ${childType.referencePath}`
10443
10776
  );
10444
10777
  }
10445
- return ` ${prop}: ${childType.resolvedType.name} | null`;
10778
+ const nullSuffix = isArrayType$1(childType.resolvedType) ? "" : " | null";
10779
+ return ` ${prop}: ${childType.resolvedType.name}${nullSuffix}`;
10446
10780
  } else
10447
10781
  throw new Error(`unknown type ${childType.name}, ${childType.kind}`);
10448
10782
  }).join(",\n");
@@ -10828,6 +11162,22 @@ const REFERENCE_MANAGER_TYPES = {
10828
11162
  function renderReferenceManager(refs, target) {
10829
11163
  const { referenceManagerInit, imports } = REFERENCE_MANAGER_TYPES[target];
10830
11164
  const options = target === 0 ? "options, " : "";
11165
+ const usedRefManagerNames = /* @__PURE__ */ new Set();
11166
+ const getUniqueRefManagerName = (baseName) => {
11167
+ const baseCamelCase = camelCase(`${baseName}RefManager`);
11168
+ if (!usedRefManagerNames.has(baseCamelCase)) {
11169
+ usedRefManagerNames.add(baseCamelCase);
11170
+ return baseCamelCase;
11171
+ }
11172
+ let suffix = 2;
11173
+ let uniqueName = `${baseCamelCase}${suffix}`;
11174
+ while (usedRefManagerNames.has(uniqueName)) {
11175
+ suffix++;
11176
+ uniqueName = `${baseCamelCase}${suffix}`;
11177
+ }
11178
+ usedRefManagerNames.add(uniqueName);
11179
+ return uniqueName;
11180
+ };
10831
11181
  const renderRefManagerNode = (name, refsTree) => {
10832
11182
  const elemRefs = refsTree.refs.filter((_) => !isComponentRef(_) && !isCollectionRef(_));
10833
11183
  const elemCollectionRefs = refsTree.refs.filter(
@@ -10850,7 +11200,7 @@ function renderReferenceManager(refs, target) {
10850
11200
  const childRenderedRefManagers = [];
10851
11201
  const childRefManagerMembers = [];
10852
11202
  Object.entries(refsTree.children).forEach(([childName, childRefNode]) => {
10853
- const name2 = camelCase(`${childName}RefManager`);
11203
+ const name2 = getUniqueRefManagerName(childName);
10854
11204
  const rendered = renderRefManagerNode(name2, childRefNode);
10855
11205
  childRefManagerMembers.push(` ${childName}: ${name2}`);
10856
11206
  childRenderedRefManagers.push(rendered);
@@ -11321,14 +11671,7 @@ ${indent.curr}return ${childElement.rendered}}, '${trackBy}')`,
11321
11671
  ]);
11322
11672
  }
11323
11673
  const accessorExpr = parseAccessor(accessor, variables);
11324
- let depth = 1;
11325
- let parent = variables;
11326
- const maxDepth = 100;
11327
- while (parent && parent.parent && depth < maxDepth) {
11328
- depth++;
11329
- parent = parent.parent;
11330
- }
11331
- const newVariables = new Variables(accessorExpr.resolvedType, variables, depth);
11674
+ const newVariables = variables.childVariableForWithData(accessorExpr);
11332
11675
  const childNodes = htmlElement.childNodes.filter(
11333
11676
  (child) => child.nodeType !== NodeType.TEXT_NODE || child.innerText.trim() !== ""
11334
11677
  );
@@ -11781,8 +12124,68 @@ ${renderedRefsManager}
11781
12124
  renderedBridge.refs
11782
12125
  );
11783
12126
  }
12127
+ function generatePhaseSpecificTypes(jayFile) {
12128
+ const baseName = jayFile.baseElementName;
12129
+ const actualViewStateTypeName = jayFile.types.name;
12130
+ if (jayFile.contract) {
12131
+ return generateAllPhaseViewStateTypes(jayFile.contract, actualViewStateTypeName);
12132
+ }
12133
+ if (jayFile.hasInlineData) {
12134
+ return [
12135
+ `export type ${baseName}SlowViewState = {};`,
12136
+ `export type ${baseName}FastViewState = {};`,
12137
+ `export type ${baseName}InteractiveViewState = ${actualViewStateTypeName};`
12138
+ ].join("\n");
12139
+ }
12140
+ return "";
12141
+ }
11784
12142
  function generateElementDefinitionFile(parsedFile) {
11785
12143
  return parsedFile.map((jayFile) => {
12144
+ const baseName = jayFile.baseElementName;
12145
+ if (jayFile.contract && jayFile.contractRef) {
12146
+ const contractFileName = path.basename(jayFile.contractRef, ".jay-contract");
12147
+ const contractImport = `import {
12148
+ ${baseName}ViewState,
12149
+ ${baseName}Refs as ${baseName}ElementRefs,
12150
+ ${baseName}SlowViewState,
12151
+ ${baseName}FastViewState,
12152
+ ${baseName}InteractiveViewState,
12153
+ ${baseName}Contract
12154
+ } from './${contractFileName}.jay-contract';`;
12155
+ const { renderedElement: renderedElement2, preRenderType: preRenderType2, renderedImplementation: renderedImplementation2 } = renderFunctionImplementation$1(
12156
+ jayFile.types,
12157
+ jayFile.body,
12158
+ jayFile.imports,
12159
+ jayFile.baseElementName,
12160
+ jayFile.namespaces,
12161
+ jayFile.headlessImports,
12162
+ RuntimeMode.WorkerTrusted,
12163
+ jayFile.headLinks
12164
+ );
12165
+ const cssImport2 = generateCssImport(jayFile);
12166
+ const runtimeImports = renderImports$1(
12167
+ renderedImplementation2.imports.plus(Import.jayElement).minus(Import.jayContract).minus(Import.HTMLElementProxy).minus(Import.HTMLElementCollectionProxy),
12168
+ ImportsFor.definition,
12169
+ jayFile.imports,
12170
+ RuntimeMode.MainTrusted
12171
+ );
12172
+ const reExports = `
12173
+ // Re-export contract types for convenience
12174
+ export { ${baseName}ViewState, ${baseName}ElementRefs, ${baseName}SlowViewState, ${baseName}FastViewState, ${baseName}InteractiveViewState, ${baseName}Contract };
12175
+ `;
12176
+ let htmlOnlyTypes = renderedElement2.replace(new RegExp(`export interface ${baseName}ViewState[\\s\\S]*?\\n}`, "g"), "").replace(
12177
+ new RegExp(`export interface ${baseName}ElementRefs[\\s\\S]*?\\n}`, "g"),
12178
+ ""
12179
+ ).replace(new RegExp(`export type ${baseName}Contract = [\\s\\S]*?;`, "g"), "");
12180
+ return [
12181
+ contractImport,
12182
+ runtimeImports,
12183
+ cssImport2,
12184
+ reExports,
12185
+ htmlOnlyTypes,
12186
+ renderFunctionDeclaration(preRenderType2)
12187
+ ].filter((_) => _ !== null && _ !== "").join("\n\n");
12188
+ }
11786
12189
  let types2 = generateTypes(jayFile.types);
11787
12190
  let { renderedRefs, renderedElement, preRenderType, renderedImplementation } = renderFunctionImplementation$1(
11788
12191
  jayFile.types,
@@ -11795,6 +12198,18 @@ function generateElementDefinitionFile(parsedFile) {
11795
12198
  jayFile.headLinks
11796
12199
  );
11797
12200
  const cssImport = generateCssImport(jayFile);
12201
+ const phaseTypes = generatePhaseSpecificTypes(jayFile);
12202
+ if (jayFile.contract || jayFile.hasInlineData) {
12203
+ const old2ParamContract = `export type ${baseName}Contract = JayContract<${baseName}ViewState, ${baseName}ElementRefs>;`;
12204
+ const new5ParamContract = `export type ${baseName}Contract = JayContract<
12205
+ ${baseName}ViewState,
12206
+ ${baseName}ElementRefs,
12207
+ ${baseName}SlowViewState,
12208
+ ${baseName}FastViewState,
12209
+ ${baseName}InteractiveViewState
12210
+ >;`;
12211
+ renderedElement = renderedElement.replace(old2ParamContract, new5ParamContract);
12212
+ }
11798
12213
  return [
11799
12214
  renderImports$1(
11800
12215
  renderedImplementation.imports.plus(Import.jayElement),
@@ -11805,6 +12220,7 @@ function generateElementDefinitionFile(parsedFile) {
11805
12220
  cssImport,
11806
12221
  types2,
11807
12222
  renderedRefs,
12223
+ phaseTypes,
11808
12224
  renderedElement,
11809
12225
  renderFunctionDeclaration(preRenderType)
11810
12226
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -11812,7 +12228,7 @@ function generateElementDefinitionFile(parsedFile) {
11812
12228
  }
11813
12229
  function generateElementFile(jayFile, importerMode) {
11814
12230
  const types2 = generateTypes(jayFile.types);
11815
- const { renderedRefs, renderedElement, renderedImplementation } = renderFunctionImplementation$1(
12231
+ let { renderedRefs, renderedElement, renderedImplementation } = renderFunctionImplementation$1(
11816
12232
  jayFile.types,
11817
12233
  jayFile.body,
11818
12234
  jayFile.imports,
@@ -11823,6 +12239,23 @@ function generateElementFile(jayFile, importerMode) {
11823
12239
  jayFile.headLinks
11824
12240
  );
11825
12241
  const cssImport = generateCssImport(jayFile);
12242
+ const phaseTypes = generatePhaseSpecificTypes(jayFile);
12243
+ if (jayFile.contract || jayFile.hasInlineData) {
12244
+ const baseName = jayFile.baseElementName;
12245
+ const contractPattern = new RegExp(
12246
+ `export type ${baseName}Contract = JayContract<([^,]+), ${baseName}ElementRefs>;`,
12247
+ "g"
12248
+ );
12249
+ renderedElement = renderedElement.replace(contractPattern, (match, viewStateType) => {
12250
+ return `export type ${baseName}Contract = JayContract<
12251
+ ${viewStateType},
12252
+ ${baseName}ElementRefs,
12253
+ ${baseName}SlowViewState,
12254
+ ${baseName}FastViewState,
12255
+ ${baseName}InteractiveViewState
12256
+ >;`;
12257
+ });
12258
+ }
11826
12259
  const renderedFile = [
11827
12260
  renderImports$1(
11828
12261
  renderedImplementation.imports.plus(Import.element).plus(Import.jayElement),
@@ -11833,6 +12266,7 @@ function generateElementFile(jayFile, importerMode) {
11833
12266
  cssImport,
11834
12267
  types2,
11835
12268
  renderedRefs,
12269
+ phaseTypes,
11836
12270
  renderedElement,
11837
12271
  renderedImplementation.rendered
11838
12272
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -11866,6 +12300,23 @@ function generateElementBridgeFile(jayFile) {
11866
12300
  refsType,
11867
12301
  jayFile.headlessImports
11868
12302
  );
12303
+ const phaseTypes = generatePhaseSpecificTypes(jayFile);
12304
+ if (jayFile.contract || jayFile.hasInlineData) {
12305
+ const baseName = jayFile.baseElementName;
12306
+ const contractPattern = new RegExp(
12307
+ `export type ${baseName}Contract = JayContract<([^,]+), ${baseName}ElementRefs>;`,
12308
+ "g"
12309
+ );
12310
+ renderedElement = renderedElement.replace(contractPattern, (match, viewStateType) => {
12311
+ return `export type ${baseName}Contract = JayContract<
12312
+ ${viewStateType},
12313
+ ${baseName}ElementRefs,
12314
+ ${baseName}SlowViewState,
12315
+ ${baseName}FastViewState,
12316
+ ${baseName}InteractiveViewState
12317
+ >;`;
12318
+ });
12319
+ }
11869
12320
  return [
11870
12321
  renderImports$1(
11871
12322
  renderedImplementation.imports.plus(Import.element).plus(Import.jayElement).plus(renderedBridge.imports),
@@ -11875,6 +12326,7 @@ function generateElementBridgeFile(jayFile) {
11875
12326
  ),
11876
12327
  types2,
11877
12328
  renderedRefs,
12329
+ phaseTypes,
11878
12330
  renderedElement,
11879
12331
  renderedBridge.rendered
11880
12332
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -15112,18 +15564,6 @@ var jsYaml = {
15112
15564
  safeLoadAll,
15113
15565
  safeDump
15114
15566
  };
15115
- function upperCaseFirst(input) {
15116
- return input.charAt(0).toUpperCase() + input.substr(1);
15117
- }
15118
- function capitalCaseTransform(input) {
15119
- return upperCaseFirst(input.toLowerCase());
15120
- }
15121
- function capitalCase(input, options) {
15122
- if (options === void 0) {
15123
- options = {};
15124
- }
15125
- return noCase(input, __assign({ delimiter: " ", transform: capitalCaseTransform }, options));
15126
- }
15127
15567
  function commonjsRequire(path2) {
15128
15568
  throw new Error('Could not dynamically require "' + path2 + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
15129
15569
  }
@@ -15479,13 +15919,6 @@ var pluralize$1 = { exports: {} };
15479
15919
  })(pluralize$1);
15480
15920
  var pluralizeExports = pluralize$1.exports;
15481
15921
  const pluralize = /* @__PURE__ */ getDefaultExportFromCjs(pluralizeExports);
15482
- var ContractTagType = /* @__PURE__ */ ((ContractTagType2) => {
15483
- ContractTagType2[ContractTagType2["data"] = 0] = "data";
15484
- ContractTagType2[ContractTagType2["interactive"] = 1] = "interactive";
15485
- ContractTagType2[ContractTagType2["variant"] = 2] = "variant";
15486
- ContractTagType2[ContractTagType2["subContract"] = 3] = "subContract";
15487
- return ContractTagType2;
15488
- })(ContractTagType || {});
15489
15922
  async function traverseTags(tags, typeName, context) {
15490
15923
  const { isRepeated, isAsync } = context;
15491
15924
  const objectTypeMembers = {};
@@ -15500,7 +15933,8 @@ async function traverseTags(tags, typeName, context) {
15500
15933
  const subContractTypes = await traverseSubContractTag(subTag, {
15501
15934
  ...context,
15502
15935
  viewStateType: objectType,
15503
- isRepeated: isRepeated || subTag.repeated,
15936
+ // For ViewState: only use the tag's own repeated flag (don't inherit from parent)
15937
+ isRepeated: subTag.repeated || false,
15504
15938
  isAsync: subTag.async
15505
15939
  });
15506
15940
  if (subContractTypes.val) {
@@ -15515,6 +15949,7 @@ async function traverseTags(tags, typeName, context) {
15515
15949
  const result = await traverseTag(subTag, {
15516
15950
  ...context,
15517
15951
  viewStateType: objectType,
15952
+ // For Refs: inherit repeated from parent (child refs in repeated parent should be collections)
15518
15953
  isRepeated: isRepeated || subTag.repeated
15519
15954
  });
15520
15955
  if (result.type && isEnumType(result.type))
@@ -15646,7 +16081,9 @@ function resolveRecursiveReferences$1(type2, rootType) {
15646
16081
  if (type2.referencePath === "$/") {
15647
16082
  type2.resolvedType = rootType;
15648
16083
  } else if (type2.referencePath.startsWith("$/")) {
15649
- const path2 = type2.referencePath.substring(2);
16084
+ const hasArrayUnwrap = type2.referencePath.endsWith("[]");
16085
+ const pathToResolve = hasArrayUnwrap ? type2.referencePath.substring(0, type2.referencePath.length - 2) : type2.referencePath;
16086
+ const path2 = pathToResolve.substring(2);
15650
16087
  const pathParts = path2.split("/");
15651
16088
  let currentType = rootType;
15652
16089
  for (const part of pathParts) {
@@ -15660,6 +16097,9 @@ function resolveRecursiveReferences$1(type2, rootType) {
15660
16097
  break;
15661
16098
  }
15662
16099
  }
16100
+ if (hasArrayUnwrap && isArrayType$1(currentType)) {
16101
+ currentType = currentType.itemType;
16102
+ }
15663
16103
  type2.resolvedType = currentType || rootType;
15664
16104
  }
15665
16105
  } else if (isArrayType$1(type2)) {
@@ -15701,6 +16141,50 @@ async function contractToImportsViewStateAndRefs(contract, contractFilePath, jay
15701
16141
  return r;
15702
16142
  });
15703
16143
  }
16144
+ async function contractToPhaseViewState(contract, contractFilePath, jayImportResolver, phase, isRepeated = false, isAsync = false) {
16145
+ const phaseContract = createPhaseContract(contract, phase);
16146
+ const phaseName = phase === "fast+interactive" ? "Interactive" : pascalCase(phase);
16147
+ const viewStateName = pascalCase(`${contract.name} ${phaseName} ViewState`);
16148
+ const result = await traverseTags(phaseContract.tags, viewStateName, {
16149
+ viewStateType: void 0,
16150
+ isRepeated,
16151
+ contractFilePath,
16152
+ importResolver: jayImportResolver,
16153
+ isAsync
16154
+ });
16155
+ return result.map((r) => {
16156
+ if (r.type) {
16157
+ const rootType = getRootObjectType(r.type);
16158
+ if (rootType) {
16159
+ resolveRecursiveReferences$1(r.type, rootType);
16160
+ }
16161
+ }
16162
+ return r;
16163
+ });
16164
+ }
16165
+ async function contractToAllPhaseViewStates(contract, contractFilePath, jayImportResolver) {
16166
+ const [slowResult, fastResult, interactiveResult] = await Promise.all([
16167
+ contractToPhaseViewState(contract, contractFilePath, jayImportResolver, "slow"),
16168
+ contractToPhaseViewState(contract, contractFilePath, jayImportResolver, "fast"),
16169
+ contractToPhaseViewState(contract, contractFilePath, jayImportResolver, "fast+interactive")
16170
+ ]);
16171
+ const validations = [
16172
+ ...slowResult.validations,
16173
+ ...fastResult.validations,
16174
+ ...interactiveResult.validations
16175
+ ];
16176
+ if (validations.length > 0 || !slowResult.val || !fastResult.val || !interactiveResult.val) {
16177
+ return new WithValidations(void 0, validations);
16178
+ }
16179
+ return new WithValidations(
16180
+ {
16181
+ slow: slowResult.val,
16182
+ fast: fastResult.val,
16183
+ interactive: interactiveResult.val
16184
+ },
16185
+ validations
16186
+ );
16187
+ }
15704
16188
  function refsToRepeated(refsTreeNode) {
15705
16189
  const { refs, children, imported } = refsTreeNode;
15706
16190
  return mkRefsTree(
@@ -15741,23 +16225,30 @@ function renderImports(imports, importedLinks) {
15741
16225
  }
15742
16226
  async function compileContract(contractWithValidations, contractFilePath, jayImportResolver) {
15743
16227
  return contractWithValidations.flatMapAsync(async (contract) => {
15744
- const contractTypes = await contractToImportsViewStateAndRefs(
16228
+ const fullViewStateResult = await contractToImportsViewStateAndRefs(
15745
16229
  contract,
15746
16230
  contractFilePath,
15747
16231
  jayImportResolver
15748
16232
  );
15749
- return contractTypes.map((contractTypesResult) => {
15750
- const { type: type2, refs, importLinks } = contractTypesResult;
15751
- const types2 = generateTypes(type2);
16233
+ return fullViewStateResult.map((fullResult) => {
16234
+ const { type: type2, refs, importLinks } = fullResult;
16235
+ const fullViewStateTypes = generateTypes(type2);
16236
+ const contractName = pascalCase(contract.name);
16237
+ const viewStateTypeName = `${contractName}ViewState`;
16238
+ const phaseViewStateTypes = generateAllPhaseViewStateTypes(contract, viewStateTypeName);
15752
16239
  let { imports, renderedRefs } = generateRefsInterface(contract, refs);
15753
16240
  imports = imports.plus(Import.jayContract);
15754
16241
  const renderedImports = renderImports(imports, importLinks);
15755
- const viewStateTypeName = `${pascalCase(contract.name)}ViewState`;
15756
- const refsTypeName = `${pascalCase(contract.name)}Refs`;
15757
- const contractType = `export type ${pascalCase(contract.name)}Contract = JayContract<${viewStateTypeName}, ${refsTypeName}>`;
16242
+ const refsTypeName = `${contractName}Refs`;
16243
+ const slowViewStateTypeName = `${contractName}SlowViewState`;
16244
+ const fastViewStateTypeName = `${contractName}FastViewState`;
16245
+ const interactiveViewStateTypeName = `${contractName}InteractiveViewState`;
16246
+ const contractType = `export type ${contractName}Contract = JayContract<${viewStateTypeName}, ${refsTypeName}, ${slowViewStateTypeName}, ${fastViewStateTypeName}, ${interactiveViewStateTypeName}>`;
15758
16247
  return `${renderedImports}
15759
16248
 
15760
- ${types2}
16249
+ ${fullViewStateTypes}
16250
+
16251
+ ${phaseViewStateTypes}
15761
16252
 
15762
16253
  ${renderedRefs}
15763
16254
 
@@ -15800,6 +16291,26 @@ function parseType(type2, tagName) {
15800
16291
  else
15801
16292
  return new WithValidations([], [`Tag [${tagName}] has an unknown tag type [${type2}]`]);
15802
16293
  }
16294
+ function parsePhase(phase, tagName, tagTypes) {
16295
+ const validations = [];
16296
+ if (!phase) {
16297
+ return new WithValidations(void 0, validations);
16298
+ }
16299
+ const validPhases = ["slow", "fast", "fast+interactive"];
16300
+ if (!validPhases.includes(phase)) {
16301
+ validations.push(
16302
+ `Tag [${tagName}] has invalid phase [${phase}]. Valid phases are: ${validPhases.join(", ")}`
16303
+ );
16304
+ return new WithValidations(void 0, validations);
16305
+ }
16306
+ if (tagTypes.includes(ContractTagType.interactive)) {
16307
+ validations.push(
16308
+ `Tag [${tagName}] of type [interactive] cannot have an explicit phase attribute (implicitly fast+interactive)`
16309
+ );
16310
+ return new WithValidations(void 0, validations);
16311
+ }
16312
+ return new WithValidations(phase, validations);
16313
+ }
15803
16314
  function parseTag(tag) {
15804
16315
  const types2 = parseType(tag.type || (tag.tags ? "sub-contract" : "data"), tag.tag);
15805
16316
  const typesAsString = types2.val.map((_) => ContractTagType[_]).join(", ");
@@ -15838,6 +16349,9 @@ function parseTag(tag) {
15838
16349
  const description = parseDescription(tag.description);
15839
16350
  const elementType = parseElementType(tag.elementType);
15840
16351
  const required = tag.required;
16352
+ const phaseResult = parsePhase(tag.phase, tag.tag, types2.val);
16353
+ validations.push(...phaseResult.validations);
16354
+ const phase = phaseResult.val;
15841
16355
  if (validations.length > 0)
15842
16356
  return new WithValidations(void 0, validations);
15843
16357
  if (types2.val.includes(ContractTagType.subContract)) {
@@ -15849,6 +16363,7 @@ function parseTag(tag) {
15849
16363
  ...required && { required },
15850
16364
  ...description && { description },
15851
16365
  ...tag.repeated && { repeated: tag.repeated },
16366
+ ...phase && { phase },
15852
16367
  link: tag.link
15853
16368
  },
15854
16369
  validations
@@ -15875,7 +16390,8 @@ function parseTag(tag) {
15875
16390
  ...description && { description },
15876
16391
  tags: parsedSubTags,
15877
16392
  ...tag.repeated && { repeated: tag.repeated },
15878
- ...tag.async && { async: tag.async }
16393
+ ...tag.async && { async: tag.async },
16394
+ ...phase && { phase }
15879
16395
  },
15880
16396
  [...validations, ...subTagValidations, ...duplicateTagValidations]
15881
16397
  );
@@ -15888,7 +16404,8 @@ function parseTag(tag) {
15888
16404
  ...parsedDataType && { dataType: parsedDataType },
15889
16405
  ...description && { description },
15890
16406
  ...elementType && { elementType },
15891
- ...tag.async && { async: tag.async }
16407
+ ...tag.async && { async: tag.async },
16408
+ ...phase && { phase }
15892
16409
  };
15893
16410
  return new WithValidations(contractTag, validations);
15894
16411
  }
@@ -15896,29 +16413,35 @@ function parseTag(tag) {
15896
16413
  function parseContract(contractYaml, fileName) {
15897
16414
  try {
15898
16415
  const parsedYaml = jsYaml.load(contractYaml);
16416
+ const validations = [];
16417
+ if (!parsedYaml.name) {
16418
+ validations.push("Contract must have a name");
16419
+ }
16420
+ if (!parsedYaml.tags && !Array.isArray(parsedYaml.tags)) {
16421
+ validations.push("Contract must have tags as an array of the contract tags");
16422
+ }
16423
+ if (validations.length > 0) {
16424
+ return new WithValidations(void 0, validations);
16425
+ }
15899
16426
  const tagResults = parsedYaml.tags.map((tag) => parseTag(tag));
15900
16427
  const tagValidations = tagResults.flatMap((tr) => tr.validations);
15901
16428
  const parsedTags = tagResults.map((tr) => tr.val).filter((tag) => !!tag);
15902
16429
  const tagNames = /* @__PURE__ */ new Set();
15903
- const duplicateTagValidations = [];
15904
16430
  parsedTags.forEach((tag) => {
15905
16431
  if (tagNames.has(tag.tag)) {
15906
- duplicateTagValidations.push(`Duplicate tag name [${tag.tag}]`);
16432
+ validations.push(`Duplicate tag name [${tag.tag}]`);
15907
16433
  }
15908
16434
  tagNames.add(tag.tag);
15909
16435
  });
15910
- const nameValidations = [];
15911
- if (!parsedYaml.name) {
15912
- nameValidations.push("Contract must have a name");
15913
- }
15914
16436
  const contract = {
15915
16437
  name: parsedYaml.name,
15916
16438
  tags: parsedTags
15917
16439
  };
16440
+ const phaseValidations = validateContractPhases(contract);
15918
16441
  return new WithValidations(contract, [
15919
16442
  ...tagValidations,
15920
- ...duplicateTagValidations,
15921
- ...nameValidations
16443
+ ...validations,
16444
+ ...phaseValidations
15922
16445
  ]);
15923
16446
  } catch (e2) {
15924
16447
  throw new Error(`failed to parse contract YAML for ${fileName}, ${e2.message}.`);
@@ -15953,7 +16476,9 @@ function parseArrayRecursiveReference(typeString) {
15953
16476
  return null;
15954
16477
  }
15955
16478
  function validateRecursivePath(referencePath, rootData, currentPath) {
15956
- const parts = referencePath.split("/").filter((p) => p);
16479
+ const hasArrayUnwrap = referencePath.endsWith("[]");
16480
+ const pathToValidate = hasArrayUnwrap ? referencePath.substring(0, referencePath.length - 2) : referencePath;
16481
+ const parts = pathToValidate.split("/").filter((p) => p);
15957
16482
  if (parts.length === 0 || parts[0] !== "$") {
15958
16483
  return `Recursive reference must start with "$/" (got: ${referencePath}). Use "$/data" or "$/data/path" format.`;
15959
16484
  }
@@ -15984,6 +16509,9 @@ function validateRecursivePath(referencePath, rootData, currentPath) {
15984
16509
  currentData = currentData[part];
15985
16510
  traversedPath.push(part);
15986
16511
  }
16512
+ if (hasArrayUnwrap && !Array.isArray(currentData)) {
16513
+ return `Recursive reference with [] unwrap syntax must point to an array type, but "$/` + traversedPath.join("/") + `" is not an array.`;
16514
+ }
15987
16515
  return void 0;
15988
16516
  }
15989
16517
  function resolveType(data, validations, path2, imports, rootData) {
@@ -16044,7 +16572,9 @@ function resolveType(data, validations, path2, imports, rootData) {
16044
16572
  }
16045
16573
  function resolveRecursiveReferences(type2, rootType, validations) {
16046
16574
  if (type2 instanceof JayRecursiveType) {
16047
- const parts = type2.referencePath.split("/").filter((p) => p);
16575
+ const hasArrayUnwrap = type2.referencePath.endsWith("[]");
16576
+ const pathToResolve = hasArrayUnwrap ? type2.referencePath.substring(0, type2.referencePath.length - 2) : type2.referencePath;
16577
+ const parts = pathToResolve.split("/").filter((p) => p);
16048
16578
  if (parts.length >= 2 && parts[0] === "$" && parts[1] === "data") {
16049
16579
  let resolvedType = rootType;
16050
16580
  const traversedPath = ["$", "data"];
@@ -16072,6 +16602,9 @@ function resolveRecursiveReferences(type2, rootType, validations) {
16072
16602
  return;
16073
16603
  }
16074
16604
  }
16605
+ if (hasArrayUnwrap && resolvedType instanceof JayArrayType) {
16606
+ resolvedType = resolvedType.itemType;
16607
+ }
16075
16608
  type2.resolvedType = resolvedType;
16076
16609
  } else if (parts.length < 2 || parts[0] !== "$" || parts[1] !== "data") {
16077
16610
  validations.push(
@@ -16088,7 +16621,43 @@ function resolveRecursiveReferences(type2, rootType, validations) {
16088
16621
  resolveRecursiveReferences(type2.itemType, rootType, validations);
16089
16622
  }
16090
16623
  }
16091
- function parseTypes(jayYaml, validations, baseElementName, imports, headlessImports) {
16624
+ async function parseTypes(jayYaml, validations, baseElementName, imports, headlessImports, filePath, importResolver) {
16625
+ if (jayYaml.contractRef) {
16626
+ const contractPath = path.resolve(filePath, jayYaml.contractRef);
16627
+ try {
16628
+ const contractResult = importResolver.loadContract(contractPath);
16629
+ validations.push(...contractResult.validations);
16630
+ if (contractResult.val) {
16631
+ jayYaml.parsedContract = contractResult.val;
16632
+ const viewStateResult = await contractToImportsViewStateAndRefs(
16633
+ contractResult.val,
16634
+ contractPath,
16635
+ importResolver
16636
+ );
16637
+ validations.push(...viewStateResult.validations);
16638
+ if (viewStateResult.val && viewStateResult.val.type) {
16639
+ const contractType = viewStateResult.val.type;
16640
+ if (contractType instanceof JayObjectType) {
16641
+ return new JayObjectType(baseElementName + "ViewState", contractType.props);
16642
+ }
16643
+ return contractType;
16644
+ } else {
16645
+ validations.push(
16646
+ `Failed to extract ViewState from contract ${jayYaml.contractRef}`
16647
+ );
16648
+ return new JayObjectType(baseElementName + "ViewState", {});
16649
+ }
16650
+ } else {
16651
+ validations.push(`Failed to load contract from ${jayYaml.contractRef}`);
16652
+ return new JayObjectType(baseElementName + "ViewState", {});
16653
+ }
16654
+ } catch (error) {
16655
+ validations.push(
16656
+ `Referenced contract file not found: ${jayYaml.contractRef} - ${error.message}`
16657
+ );
16658
+ return new JayObjectType(baseElementName + "ViewState", {});
16659
+ }
16660
+ }
16092
16661
  if (typeof jayYaml.data === "object") {
16093
16662
  const resolvedType = resolveType(
16094
16663
  jayYaml.data,
@@ -16129,8 +16698,27 @@ function parseYaml(root) {
16129
16698
  );
16130
16699
  return new WithValidations(void 0, validations);
16131
16700
  }
16132
- let jayYaml = jayYamlElements[0].text;
16133
- let jayYamlParsed = jsYaml.load(jayYaml);
16701
+ const jayYamlElement = jayYamlElements[0];
16702
+ const contractAttr = jayYamlElement.getAttribute("contract");
16703
+ const jayYamlText = jayYamlElement.text.trim();
16704
+ if (contractAttr) {
16705
+ if (jayYamlText && jayYamlText.length > 0) {
16706
+ validations.push(
16707
+ `Cannot have both 'contract' attribute and inline data structure. Either reference a contract file or define data inline, not both.`
16708
+ );
16709
+ return new WithValidations(void 0, validations);
16710
+ }
16711
+ return new WithValidations(
16712
+ {
16713
+ contractRef: contractAttr,
16714
+ imports: {},
16715
+ examples: void 0
16716
+ },
16717
+ validations
16718
+ );
16719
+ }
16720
+ let jayYamlParsed = jsYaml.load(jayYamlText);
16721
+ jayYamlParsed.hasInlineData = true;
16134
16722
  return new WithValidations(jayYamlParsed, validations);
16135
16723
  }
16136
16724
  function parseHeadfullImports(elements, validations, filePath, options, importResolver) {
@@ -16353,7 +16941,15 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
16353
16941
  linkedContractResolver
16354
16942
  );
16355
16943
  const importNames = headfullImports.flatMap((_) => _.names);
16356
- const types2 = parseTypes(jayYaml, validations, baseElementName, importNames, headlessImports);
16944
+ const types2 = await parseTypes(
16945
+ jayYaml,
16946
+ validations,
16947
+ baseElementName,
16948
+ importNames,
16949
+ headlessImports,
16950
+ filePath,
16951
+ linkedContractResolver
16952
+ );
16357
16953
  const imports = [
16358
16954
  ...headfullImports,
16359
16955
  ...headlessImports.flatMap((_) => _.contractLinks)
@@ -16380,7 +16976,10 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
16380
16976
  headlessImports,
16381
16977
  headLinks,
16382
16978
  css: cssResult.val,
16383
- filename: normalizedFileName
16979
+ filename: normalizedFileName,
16980
+ contract: jayYaml.parsedContract,
16981
+ contractRef: jayYaml.contractRef,
16982
+ hasInlineData: jayYaml.hasInlineData
16384
16983
  },
16385
16984
  validations
16386
16985
  );
@@ -16411,7 +17010,9 @@ export {
16411
17010
  ContractTagType,
16412
17011
  JAY_IMPORT_RESOLVER,
16413
17012
  compileContract,
17013
+ contractToAllPhaseViewStates,
16414
17014
  contractToImportsViewStateAndRefs,
17015
+ contractToPhaseViewState,
16415
17016
  generateElementBridgeFile,
16416
17017
  generateElementDefinitionFile,
16417
17018
  generateElementFile,