@jay-framework/compiler-jay-html 0.7.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
  }
@@ -10394,7 +10727,8 @@ function renderInterface(aType) {
10394
10727
  genInterface += Object.keys(aType.props).map((prop) => {
10395
10728
  let childType = aType.props[prop];
10396
10729
  if (childType instanceof JayImportedType) {
10397
- return ` ${prop}: ${childType.name}`;
10730
+ const optional = childType.isOptional ? "?" : "";
10731
+ return ` ${prop}${optional}: ${childType.name}`;
10398
10732
  } else if (isObjectType$1(childType)) {
10399
10733
  childInterfaces.push(renderInterface(childType));
10400
10734
  return ` ${prop}: ${childType.name}`;
@@ -10441,7 +10775,8 @@ ${childType.values.map((_) => " " + _).join(",\n")}
10441
10775
  `Recursive type not resolved: ${childType.referencePath}`
10442
10776
  );
10443
10777
  }
10444
- return ` ${prop}: ${childType.resolvedType.name} | null`;
10778
+ const nullSuffix = isArrayType$1(childType.resolvedType) ? "" : " | null";
10779
+ return ` ${prop}: ${childType.resolvedType.name}${nullSuffix}`;
10445
10780
  } else
10446
10781
  throw new Error(`unknown type ${childType.name}, ${childType.kind}`);
10447
10782
  }).join(",\n");
@@ -10827,6 +11162,22 @@ const REFERENCE_MANAGER_TYPES = {
10827
11162
  function renderReferenceManager(refs, target) {
10828
11163
  const { referenceManagerInit, imports } = REFERENCE_MANAGER_TYPES[target];
10829
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
+ };
10830
11181
  const renderRefManagerNode = (name, refsTree) => {
10831
11182
  const elemRefs = refsTree.refs.filter((_) => !isComponentRef(_) && !isCollectionRef(_));
10832
11183
  const elemCollectionRefs = refsTree.refs.filter(
@@ -10849,7 +11200,7 @@ function renderReferenceManager(refs, target) {
10849
11200
  const childRenderedRefManagers = [];
10850
11201
  const childRefManagerMembers = [];
10851
11202
  Object.entries(refsTree.children).forEach(([childName, childRefNode]) => {
10852
- const name2 = camelCase(`${childName}RefManager`);
11203
+ const name2 = getUniqueRefManagerName(childName);
10853
11204
  const rendered = renderRefManagerNode(name2, childRefNode);
10854
11205
  childRefManagerMembers.push(` ${childName}: ${name2}`);
10855
11206
  childRenderedRefManagers.push(rendered);
@@ -11281,7 +11632,8 @@ ${indent.curr}return ${childElement.rendered}}, '${trackBy}')`,
11281
11632
  `${indent.firstLine}${asyncType.name}${resolvedGenericTypes}(${getPromiseFragment.rendered}, () => ${childElement.rendered.trim()})`,
11282
11633
  childElement.imports.plus(asyncType.import),
11283
11634
  [...getPromiseFragment.validations, ...childElement.validations],
11284
- childElement.refs
11635
+ childElement.refs,
11636
+ [...getPromiseFragment.recursiveRegions, ...childElement.recursiveRegions]
11285
11637
  );
11286
11638
  }
11287
11639
  function renderNestedComponent(htmlElement, newContext) {
@@ -11319,14 +11671,7 @@ ${indent.curr}return ${childElement.rendered}}, '${trackBy}')`,
11319
11671
  ]);
11320
11672
  }
11321
11673
  const accessorExpr = parseAccessor(accessor, variables);
11322
- let depth = 1;
11323
- let parent = variables;
11324
- const maxDepth = 100;
11325
- while (parent && parent.parent && depth < maxDepth) {
11326
- depth++;
11327
- parent = parent.parent;
11328
- }
11329
- const newVariables = new Variables(accessorExpr.resolvedType, variables, depth);
11674
+ const newVariables = variables.childVariableForWithData(accessorExpr);
11330
11675
  const childNodes = htmlElement.childNodes.filter(
11331
11676
  (child) => child.nodeType !== NodeType.TEXT_NODE || child.innerText.trim() !== ""
11332
11677
  );
@@ -11341,12 +11686,13 @@ ${indent.curr}return ${childElement.rendered}}, '${trackBy}')`,
11341
11686
  indent
11342
11687
  });
11343
11688
  const accessorFunction = `(${variables.currentVar}: ${variables.currentType.name}) => ${accessorExpr.render().rendered}`;
11689
+ const nestedChildElement = nestRefs(accessorExpr.terms, childElement);
11344
11690
  return new RenderFragment(
11345
- `${indent.firstLine}withData(${accessorFunction}, () => ${childElement.rendered})`,
11346
- childElement.imports.plus(Import.withData).plus(accessorExpr.render().imports),
11347
- [...accessorExpr.validations, ...childElement.validations],
11348
- childElement.refs,
11349
- childElement.recursiveRegions
11691
+ `${indent.firstLine}withData(${accessorFunction}, () => ${nestedChildElement.rendered})`,
11692
+ nestedChildElement.imports.plus(Import.withData).plus(accessorExpr.render().imports),
11693
+ [...accessorExpr.validations, ...nestedChildElement.validations],
11694
+ nestedChildElement.refs,
11695
+ nestedChildElement.recursiveRegions
11350
11696
  );
11351
11697
  } else if (isRecurse(htmlElement)) {
11352
11698
  const refAttr = htmlElement.getAttribute("ref");
@@ -11778,8 +12124,68 @@ ${renderedRefsManager}
11778
12124
  renderedBridge.refs
11779
12125
  );
11780
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
+ }
11781
12142
  function generateElementDefinitionFile(parsedFile) {
11782
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
+ }
11783
12189
  let types2 = generateTypes(jayFile.types);
11784
12190
  let { renderedRefs, renderedElement, preRenderType, renderedImplementation } = renderFunctionImplementation$1(
11785
12191
  jayFile.types,
@@ -11792,6 +12198,18 @@ function generateElementDefinitionFile(parsedFile) {
11792
12198
  jayFile.headLinks
11793
12199
  );
11794
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
+ }
11795
12213
  return [
11796
12214
  renderImports$1(
11797
12215
  renderedImplementation.imports.plus(Import.jayElement),
@@ -11802,6 +12220,7 @@ function generateElementDefinitionFile(parsedFile) {
11802
12220
  cssImport,
11803
12221
  types2,
11804
12222
  renderedRefs,
12223
+ phaseTypes,
11805
12224
  renderedElement,
11806
12225
  renderFunctionDeclaration(preRenderType)
11807
12226
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -11809,7 +12228,7 @@ function generateElementDefinitionFile(parsedFile) {
11809
12228
  }
11810
12229
  function generateElementFile(jayFile, importerMode) {
11811
12230
  const types2 = generateTypes(jayFile.types);
11812
- const { renderedRefs, renderedElement, renderedImplementation } = renderFunctionImplementation$1(
12231
+ let { renderedRefs, renderedElement, renderedImplementation } = renderFunctionImplementation$1(
11813
12232
  jayFile.types,
11814
12233
  jayFile.body,
11815
12234
  jayFile.imports,
@@ -11820,6 +12239,23 @@ function generateElementFile(jayFile, importerMode) {
11820
12239
  jayFile.headLinks
11821
12240
  );
11822
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
+ }
11823
12259
  const renderedFile = [
11824
12260
  renderImports$1(
11825
12261
  renderedImplementation.imports.plus(Import.element).plus(Import.jayElement),
@@ -11830,6 +12266,7 @@ function generateElementFile(jayFile, importerMode) {
11830
12266
  cssImport,
11831
12267
  types2,
11832
12268
  renderedRefs,
12269
+ phaseTypes,
11833
12270
  renderedElement,
11834
12271
  renderedImplementation.rendered
11835
12272
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -11863,6 +12300,23 @@ function generateElementBridgeFile(jayFile) {
11863
12300
  refsType,
11864
12301
  jayFile.headlessImports
11865
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
+ }
11866
12320
  return [
11867
12321
  renderImports$1(
11868
12322
  renderedImplementation.imports.plus(Import.element).plus(Import.jayElement).plus(renderedBridge.imports),
@@ -11872,6 +12326,7 @@ function generateElementBridgeFile(jayFile) {
11872
12326
  ),
11873
12327
  types2,
11874
12328
  renderedRefs,
12329
+ phaseTypes,
11875
12330
  renderedElement,
11876
12331
  renderedBridge.rendered
11877
12332
  ].filter((_) => _ !== null && _ !== "").join("\n\n");
@@ -15109,18 +15564,6 @@ var jsYaml = {
15109
15564
  safeLoadAll,
15110
15565
  safeDump
15111
15566
  };
15112
- function upperCaseFirst(input) {
15113
- return input.charAt(0).toUpperCase() + input.substr(1);
15114
- }
15115
- function capitalCaseTransform(input) {
15116
- return upperCaseFirst(input.toLowerCase());
15117
- }
15118
- function capitalCase(input, options) {
15119
- if (options === void 0) {
15120
- options = {};
15121
- }
15122
- return noCase(input, __assign({ delimiter: " ", transform: capitalCaseTransform }, options));
15123
- }
15124
15567
  function commonjsRequire(path2) {
15125
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.');
15126
15569
  }
@@ -15476,13 +15919,6 @@ var pluralize$1 = { exports: {} };
15476
15919
  })(pluralize$1);
15477
15920
  var pluralizeExports = pluralize$1.exports;
15478
15921
  const pluralize = /* @__PURE__ */ getDefaultExportFromCjs(pluralizeExports);
15479
- var ContractTagType = /* @__PURE__ */ ((ContractTagType2) => {
15480
- ContractTagType2[ContractTagType2["data"] = 0] = "data";
15481
- ContractTagType2[ContractTagType2["interactive"] = 1] = "interactive";
15482
- ContractTagType2[ContractTagType2["variant"] = 2] = "variant";
15483
- ContractTagType2[ContractTagType2["subContract"] = 3] = "subContract";
15484
- return ContractTagType2;
15485
- })(ContractTagType || {});
15486
15922
  async function traverseTags(tags, typeName, context) {
15487
15923
  const { isRepeated, isAsync } = context;
15488
15924
  const objectTypeMembers = {};
@@ -15497,7 +15933,8 @@ async function traverseTags(tags, typeName, context) {
15497
15933
  const subContractTypes = await traverseSubContractTag(subTag, {
15498
15934
  ...context,
15499
15935
  viewStateType: objectType,
15500
- 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,
15501
15938
  isAsync: subTag.async
15502
15939
  });
15503
15940
  if (subContractTypes.val) {
@@ -15512,6 +15949,7 @@ async function traverseTags(tags, typeName, context) {
15512
15949
  const result = await traverseTag(subTag, {
15513
15950
  ...context,
15514
15951
  viewStateType: objectType,
15952
+ // For Refs: inherit repeated from parent (child refs in repeated parent should be collections)
15515
15953
  isRepeated: isRepeated || subTag.repeated
15516
15954
  });
15517
15955
  if (result.type && isEnumType(result.type))
@@ -15643,7 +16081,9 @@ function resolveRecursiveReferences$1(type2, rootType) {
15643
16081
  if (type2.referencePath === "$/") {
15644
16082
  type2.resolvedType = rootType;
15645
16083
  } else if (type2.referencePath.startsWith("$/")) {
15646
- 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);
15647
16087
  const pathParts = path2.split("/");
15648
16088
  let currentType = rootType;
15649
16089
  for (const part of pathParts) {
@@ -15657,6 +16097,9 @@ function resolveRecursiveReferences$1(type2, rootType) {
15657
16097
  break;
15658
16098
  }
15659
16099
  }
16100
+ if (hasArrayUnwrap && isArrayType$1(currentType)) {
16101
+ currentType = currentType.itemType;
16102
+ }
15660
16103
  type2.resolvedType = currentType || rootType;
15661
16104
  }
15662
16105
  } else if (isArrayType$1(type2)) {
@@ -15698,6 +16141,50 @@ async function contractToImportsViewStateAndRefs(contract, contractFilePath, jay
15698
16141
  return r;
15699
16142
  });
15700
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
+ }
15701
16188
  function refsToRepeated(refsTreeNode) {
15702
16189
  const { refs, children, imported } = refsTreeNode;
15703
16190
  return mkRefsTree(
@@ -15738,23 +16225,30 @@ function renderImports(imports, importedLinks) {
15738
16225
  }
15739
16226
  async function compileContract(contractWithValidations, contractFilePath, jayImportResolver) {
15740
16227
  return contractWithValidations.flatMapAsync(async (contract) => {
15741
- const contractTypes = await contractToImportsViewStateAndRefs(
16228
+ const fullViewStateResult = await contractToImportsViewStateAndRefs(
15742
16229
  contract,
15743
16230
  contractFilePath,
15744
16231
  jayImportResolver
15745
16232
  );
15746
- return contractTypes.map((contractTypesResult) => {
15747
- const { type: type2, refs, importLinks } = contractTypesResult;
15748
- 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);
15749
16239
  let { imports, renderedRefs } = generateRefsInterface(contract, refs);
15750
16240
  imports = imports.plus(Import.jayContract);
15751
16241
  const renderedImports = renderImports(imports, importLinks);
15752
- const viewStateTypeName = `${pascalCase(contract.name)}ViewState`;
15753
- const refsTypeName = `${pascalCase(contract.name)}Refs`;
15754
- 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}>`;
15755
16247
  return `${renderedImports}
15756
16248
 
15757
- ${types2}
16249
+ ${fullViewStateTypes}
16250
+
16251
+ ${phaseViewStateTypes}
15758
16252
 
15759
16253
  ${renderedRefs}
15760
16254
 
@@ -15797,6 +16291,26 @@ function parseType(type2, tagName) {
15797
16291
  else
15798
16292
  return new WithValidations([], [`Tag [${tagName}] has an unknown tag type [${type2}]`]);
15799
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
+ }
15800
16314
  function parseTag(tag) {
15801
16315
  const types2 = parseType(tag.type || (tag.tags ? "sub-contract" : "data"), tag.tag);
15802
16316
  const typesAsString = types2.val.map((_) => ContractTagType[_]).join(", ");
@@ -15835,6 +16349,9 @@ function parseTag(tag) {
15835
16349
  const description = parseDescription(tag.description);
15836
16350
  const elementType = parseElementType(tag.elementType);
15837
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;
15838
16355
  if (validations.length > 0)
15839
16356
  return new WithValidations(void 0, validations);
15840
16357
  if (types2.val.includes(ContractTagType.subContract)) {
@@ -15846,6 +16363,7 @@ function parseTag(tag) {
15846
16363
  ...required && { required },
15847
16364
  ...description && { description },
15848
16365
  ...tag.repeated && { repeated: tag.repeated },
16366
+ ...phase && { phase },
15849
16367
  link: tag.link
15850
16368
  },
15851
16369
  validations
@@ -15872,7 +16390,8 @@ function parseTag(tag) {
15872
16390
  ...description && { description },
15873
16391
  tags: parsedSubTags,
15874
16392
  ...tag.repeated && { repeated: tag.repeated },
15875
- ...tag.async && { async: tag.async }
16393
+ ...tag.async && { async: tag.async },
16394
+ ...phase && { phase }
15876
16395
  },
15877
16396
  [...validations, ...subTagValidations, ...duplicateTagValidations]
15878
16397
  );
@@ -15885,7 +16404,8 @@ function parseTag(tag) {
15885
16404
  ...parsedDataType && { dataType: parsedDataType },
15886
16405
  ...description && { description },
15887
16406
  ...elementType && { elementType },
15888
- ...tag.async && { async: tag.async }
16407
+ ...tag.async && { async: tag.async },
16408
+ ...phase && { phase }
15889
16409
  };
15890
16410
  return new WithValidations(contractTag, validations);
15891
16411
  }
@@ -15893,29 +16413,35 @@ function parseTag(tag) {
15893
16413
  function parseContract(contractYaml, fileName) {
15894
16414
  try {
15895
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
+ }
15896
16426
  const tagResults = parsedYaml.tags.map((tag) => parseTag(tag));
15897
16427
  const tagValidations = tagResults.flatMap((tr) => tr.validations);
15898
16428
  const parsedTags = tagResults.map((tr) => tr.val).filter((tag) => !!tag);
15899
16429
  const tagNames = /* @__PURE__ */ new Set();
15900
- const duplicateTagValidations = [];
15901
16430
  parsedTags.forEach((tag) => {
15902
16431
  if (tagNames.has(tag.tag)) {
15903
- duplicateTagValidations.push(`Duplicate tag name [${tag.tag}]`);
16432
+ validations.push(`Duplicate tag name [${tag.tag}]`);
15904
16433
  }
15905
16434
  tagNames.add(tag.tag);
15906
16435
  });
15907
- const nameValidations = [];
15908
- if (!parsedYaml.name) {
15909
- nameValidations.push("Contract must have a name");
15910
- }
15911
16436
  const contract = {
15912
16437
  name: parsedYaml.name,
15913
16438
  tags: parsedTags
15914
16439
  };
16440
+ const phaseValidations = validateContractPhases(contract);
15915
16441
  return new WithValidations(contract, [
15916
16442
  ...tagValidations,
15917
- ...duplicateTagValidations,
15918
- ...nameValidations
16443
+ ...validations,
16444
+ ...phaseValidations
15919
16445
  ]);
15920
16446
  } catch (e2) {
15921
16447
  throw new Error(`failed to parse contract YAML for ${fileName}, ${e2.message}.`);
@@ -15950,7 +16476,9 @@ function parseArrayRecursiveReference(typeString) {
15950
16476
  return null;
15951
16477
  }
15952
16478
  function validateRecursivePath(referencePath, rootData, currentPath) {
15953
- 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);
15954
16482
  if (parts.length === 0 || parts[0] !== "$") {
15955
16483
  return `Recursive reference must start with "$/" (got: ${referencePath}). Use "$/data" or "$/data/path" format.`;
15956
16484
  }
@@ -15968,6 +16496,12 @@ function validateRecursivePath(referencePath, rootData, currentPath) {
15968
16496
  const traversedPath = ["data"];
15969
16497
  for (let i = 1; i < pathParts.length; i++) {
15970
16498
  const part = pathParts[i];
16499
+ if (Array.isArray(currentData)) {
16500
+ if (currentData.length === 0) {
16501
+ return `Cannot navigate through empty array at path "$/` + traversedPath.join("/") + `"`;
16502
+ }
16503
+ currentData = currentData[0];
16504
+ }
15971
16505
  if (!currentData || typeof currentData !== "object" || !(part in currentData)) {
15972
16506
  const availableKeys = currentData && typeof currentData === "object" ? Object.keys(currentData) : [];
15973
16507
  return `Property "${part}" not found at path "$/` + traversedPath.join("/") + `"` + (availableKeys.length > 0 ? `. Available properties: ${availableKeys.join(", ")}` : "");
@@ -15975,6 +16509,9 @@ function validateRecursivePath(referencePath, rootData, currentPath) {
15975
16509
  currentData = currentData[part];
15976
16510
  traversedPath.push(part);
15977
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
+ }
15978
16515
  return void 0;
15979
16516
  }
15980
16517
  function resolveType(data, validations, path2, imports, rootData) {
@@ -16035,7 +16572,9 @@ function resolveType(data, validations, path2, imports, rootData) {
16035
16572
  }
16036
16573
  function resolveRecursiveReferences(type2, rootType, validations) {
16037
16574
  if (type2 instanceof JayRecursiveType) {
16038
- 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);
16039
16578
  if (parts.length >= 2 && parts[0] === "$" && parts[1] === "data") {
16040
16579
  let resolvedType = rootType;
16041
16580
  const traversedPath = ["$", "data"];
@@ -16063,6 +16602,9 @@ function resolveRecursiveReferences(type2, rootType, validations) {
16063
16602
  return;
16064
16603
  }
16065
16604
  }
16605
+ if (hasArrayUnwrap && resolvedType instanceof JayArrayType) {
16606
+ resolvedType = resolvedType.itemType;
16607
+ }
16066
16608
  type2.resolvedType = resolvedType;
16067
16609
  } else if (parts.length < 2 || parts[0] !== "$" || parts[1] !== "data") {
16068
16610
  validations.push(
@@ -16079,7 +16621,43 @@ function resolveRecursiveReferences(type2, rootType, validations) {
16079
16621
  resolveRecursiveReferences(type2.itemType, rootType, validations);
16080
16622
  }
16081
16623
  }
16082
- 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
+ }
16083
16661
  if (typeof jayYaml.data === "object") {
16084
16662
  const resolvedType = resolveType(
16085
16663
  jayYaml.data,
@@ -16090,7 +16668,10 @@ function parseTypes(jayYaml, validations, baseElementName, imports, headlessImpo
16090
16668
  // Pass root data for recursive reference validation
16091
16669
  );
16092
16670
  const headlessImportedTypes = Object.fromEntries(
16093
- headlessImports.map((_) => [_.key, new JayImportedType(_.rootType.name, _.rootType)])
16671
+ headlessImports.map((_) => [
16672
+ _.key,
16673
+ new JayImportedType(_.rootType.name, _.rootType, true)
16674
+ ])
16094
16675
  );
16095
16676
  const finalType = new JayObjectType(resolvedType.name, {
16096
16677
  ...headlessImportedTypes,
@@ -16117,8 +16698,27 @@ function parseYaml(root) {
16117
16698
  );
16118
16699
  return new WithValidations(void 0, validations);
16119
16700
  }
16120
- let jayYaml = jayYamlElements[0].text;
16121
- 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;
16122
16722
  return new WithValidations(jayYamlParsed, validations);
16123
16723
  }
16124
16724
  function parseHeadfullImports(elements, validations, filePath, options, importResolver) {
@@ -16341,7 +16941,15 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
16341
16941
  linkedContractResolver
16342
16942
  );
16343
16943
  const importNames = headfullImports.flatMap((_) => _.names);
16344
- 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
+ );
16345
16953
  const imports = [
16346
16954
  ...headfullImports,
16347
16955
  ...headlessImports.flatMap((_) => _.contractLinks)
@@ -16368,7 +16976,10 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
16368
16976
  headlessImports,
16369
16977
  headLinks,
16370
16978
  css: cssResult.val,
16371
- filename: normalizedFileName
16979
+ filename: normalizedFileName,
16980
+ contract: jayYaml.parsedContract,
16981
+ contractRef: jayYaml.contractRef,
16982
+ hasInlineData: jayYaml.hasInlineData
16372
16983
  },
16373
16984
  validations
16374
16985
  );
@@ -16399,7 +17010,9 @@ export {
16399
17010
  ContractTagType,
16400
17011
  JAY_IMPORT_RESOLVER,
16401
17012
  compileContract,
17013
+ contractToAllPhaseViewStates,
16402
17014
  contractToImportsViewStateAndRefs,
17015
+ contractToPhaseViewState,
16403
17016
  generateElementBridgeFile,
16404
17017
  generateElementDefinitionFile,
16405
17018
  generateElementFile,