@zeus-js/component-analyzer 0.1.0-beta.3 → 0.1.0-beta.4

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * component-analyzer v0.1.0-beta.3
2
+ * component-analyzer v0.1.0-beta.4
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -29,9 +29,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  enumerable: true
30
30
  }) : target, mod));
31
31
  //#endregion
32
- let _babel_parser = require("@babel/parser");
33
32
  let _babel_types = require("@babel/types");
34
33
  _babel_types = __toESM(_babel_types, 1);
34
+ let _babel_parser = require("@babel/parser");
35
35
  let node_fs_promises = require("node:fs/promises");
36
36
  node_fs_promises = __toESM(node_fs_promises, 1);
37
37
  let node_path = require("node:path");
@@ -181,24 +181,144 @@ function uniqueSorted(values) {
181
181
  return Array.from(new Set(values)).sort();
182
182
  }
183
183
  //#endregion
184
+ //#region packages/web-c/component-analyzer/src/extractEmits.ts
185
+ function extractEmits(options) {
186
+ const emitsNode = options ? getObjectProperty(options, "emits") : void 0;
187
+ if (!_babel_types.isObjectExpression(emitsNode)) return {};
188
+ const events = {};
189
+ for (const member of emitsNode.properties) {
190
+ if (!_babel_types.isObjectProperty(member) || member.computed) continue;
191
+ const key = getObjectKey(member.key);
192
+ if (!key) continue;
193
+ events[key] = extractEventDefinition(key, member.value);
194
+ }
195
+ return events;
196
+ }
197
+ function createComponentEvent(key, detail) {
198
+ return {
199
+ key,
200
+ name: toKebabCase$1(key),
201
+ reactName: toReactEventProp(key),
202
+ detail,
203
+ bubbles: true,
204
+ composed: true,
205
+ cancelable: false
206
+ };
207
+ }
208
+ function extractEventDefinition(key, node) {
209
+ var _extractEventDetailTy;
210
+ const result = createComponentEvent(key);
211
+ if (!_babel_types.isCallExpression(node)) return result;
212
+ if (!_babel_types.isIdentifier(node.callee, { name: "event" })) return result;
213
+ result.detail = (_extractEventDetailTy = extractEventDetailType(node)) !== null && _extractEventDetailTy !== void 0 ? _extractEventDetailTy : result.detail;
214
+ const first = node.arguments[0];
215
+ if (_babel_types.isStringLiteral(first)) {
216
+ result.name = first.value;
217
+ return result;
218
+ }
219
+ if (_babel_types.isObjectExpression(first)) {
220
+ const name = getObjectProperty(first, "name");
221
+ const bubbles = getObjectProperty(first, "bubbles");
222
+ const composed = getObjectProperty(first, "composed");
223
+ const cancelable = getObjectProperty(first, "cancelable");
224
+ const nameValue = staticValue(name);
225
+ const bubblesValue = staticValue(bubbles);
226
+ const composedValue = staticValue(composed);
227
+ const cancelableValue = staticValue(cancelable);
228
+ if (typeof nameValue === "string") result.name = nameValue;
229
+ if (typeof bubblesValue === "boolean") result.bubbles = bubblesValue;
230
+ if (typeof composedValue === "boolean") result.composed = composedValue;
231
+ if (typeof cancelableValue === "boolean") result.cancelable = cancelableValue;
232
+ }
233
+ return result;
234
+ }
235
+ function extractEventDetailType(node) {
236
+ var _node$typeParameters;
237
+ const first = (_node$typeParameters = node.typeParameters) === null || _node$typeParameters === void 0 ? void 0 : _node$typeParameters.params[0];
238
+ if (!_babel_types.isTSTypeLiteral(first)) return void 0;
239
+ const detail = {};
240
+ for (const member of first.members) {
241
+ var _member$typeAnnotatio;
242
+ if (!_babel_types.isTSPropertySignature(member)) continue;
243
+ const key = getObjectKey(member.key);
244
+ if (!key) continue;
245
+ detail[key] = inferTsType((_member$typeAnnotatio = member.typeAnnotation) === null || _member$typeAnnotatio === void 0 ? void 0 : _member$typeAnnotatio.typeAnnotation);
246
+ }
247
+ return Object.keys(detail).length > 0 ? detail : void 0;
248
+ }
249
+ function inferTsType(node) {
250
+ if (!node) return "unknown";
251
+ if (_babel_types.isTSStringKeyword(node)) return "string";
252
+ if (_babel_types.isTSNumberKeyword(node)) return "number";
253
+ if (_babel_types.isTSBooleanKeyword(node)) return "boolean";
254
+ if (_babel_types.isTSObjectKeyword(node) || _babel_types.isTSTypeLiteral(node)) return "object";
255
+ if (_babel_types.isTSArrayType(node) || _babel_types.isTSTupleType(node)) return "array";
256
+ if (_babel_types.isTSFunctionType(node)) return "function";
257
+ if (_babel_types.isTSTypeReference(node)) return inferTsTypeReference(node);
258
+ return "unknown";
259
+ }
260
+ function inferTsTypeReference(node) {
261
+ const name = _babel_types.isIdentifier(node.typeName) ? node.typeName.name : void 0;
262
+ switch (name) {
263
+ case "String": return "string";
264
+ case "Number": return "number";
265
+ case "Boolean": return "boolean";
266
+ case "Array":
267
+ case "ReadonlyArray": return "array";
268
+ case "Function": return "function";
269
+ case "Record": return "object";
270
+ default: return name !== null && name !== void 0 ? name : "unknown";
271
+ }
272
+ }
273
+ function toKebabCase$1(value) {
274
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
275
+ }
276
+ function toReactEventProp(value) {
277
+ return `on${value.split("-").filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("")}`;
278
+ }
279
+ //#endregion
184
280
  //#region packages/web-c/component-analyzer/src/extractMeta.ts
185
281
  function extractInlineMeta(options) {
186
282
  if (!options) return {};
187
283
  const metaNode = getObjectProperty(options, "meta");
188
- if (!_babel_types.isObjectExpression(metaNode)) return {};
189
- const value = staticValue(metaNode);
190
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
191
- return value;
284
+ const result = {};
285
+ if (_babel_types.isObjectExpression(metaNode)) {
286
+ const value = staticValue(metaNode);
287
+ if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(result, value);
288
+ }
289
+ assignTopLevelStaticValue(options, result, "slots");
290
+ assignTopLevelStaticValue(options, result, "parts");
291
+ assignTopLevelStaticValue(options, result, "cssVars");
292
+ assignTopLevelStaticValue(options, result, "methods");
293
+ assignTopLevelStaticValue(options, result, "models");
294
+ return result;
295
+ }
296
+ function assignTopLevelStaticValue(options, result, key) {
297
+ const node = getObjectProperty(options, key);
298
+ if (!node) return;
299
+ const value = staticValue(node);
300
+ if (key === "parts") {
301
+ result.cssParts = Array.isArray(value) ? value.filter((item) => typeof item === "string") : result.cssParts;
302
+ return;
303
+ }
304
+ result[key] = value;
192
305
  }
193
306
  //#endregion
194
307
  //#region packages/web-c/component-analyzer/src/extractProps.ts
195
- function extractShadowOption(options) {
308
+ function extractComponentOptions(options) {
196
309
  if (!options) return {};
310
+ const result = {};
197
311
  const shadowNode = getObjectProperty(options, "shadow");
198
- if (!shadowNode) return {};
199
- const value = staticValue(shadowNode);
200
- if (typeof value !== "boolean") return {};
201
- return { shadow: value };
312
+ if (shadowNode) {
313
+ const value = staticValue(shadowNode);
314
+ if (typeof value === "boolean") result.shadow = value;
315
+ }
316
+ const formAssociatedNode = getObjectProperty(options, "formAssociated");
317
+ if (formAssociatedNode) {
318
+ const value = staticValue(formAssociatedNode);
319
+ if (typeof value === "boolean") result.formAssociated = value;
320
+ }
321
+ return result;
202
322
  }
203
323
  function extractRuntimeProps(options) {
204
324
  if (!options) return {};
@@ -238,11 +358,15 @@ function validateRuntimePropsDefinition(options, optionsArgument) {
238
358
  continue;
239
359
  }
240
360
  if (_babel_types.isIdentifier(member.value)) {
241
- if (!isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" must use String, Number, Boolean, Object, Array, or an inline prop options object.`);
361
+ if (!isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" must use String, Number, Boolean, Object, Array, Function, prop(values), prop(Constructor), or an inline prop options object.`);
362
+ continue;
363
+ }
364
+ if (isPropCall(member.value)) {
365
+ validatePropCall(propName, member.value, messages);
242
366
  continue;
243
367
  }
244
368
  if (!_babel_types.isObjectExpression(member.value)) {
245
- messages.push(`Prop "${propName}" must use an inline prop options object.`);
369
+ messages.push(`Prop "${propName}" must use an inline prop options object, prop(values), or prop(Constructor).`);
246
370
  continue;
247
371
  }
248
372
  validatePropOptions(propName, member.value, messages);
@@ -261,7 +385,7 @@ function validatePropOptions(propName, options, messages) {
261
385
  continue;
262
386
  }
263
387
  if (optionName === "type") {
264
- if (!_babel_types.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, or Array.`);
388
+ if (!_babel_types.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, Array, or Function.`);
265
389
  continue;
266
390
  }
267
391
  if (optionName === "attr") {
@@ -280,16 +404,27 @@ function validatePropOptions(propName, options, messages) {
280
404
  continue;
281
405
  }
282
406
  if (value !== void 0 && typeof value !== "boolean") messages.push(`Prop "${propName}" reflect must be a static boolean.`);
407
+ continue;
408
+ }
409
+ if (optionName === "values") {
410
+ if (!isStaticStringArray(member.value)) messages.push(`Prop "${propName}" values must be a static string array.`);
411
+ continue;
412
+ }
413
+ if (optionName === "serialize" || optionName === "deserialize") {
414
+ if (!isFunctionLikeReference(member.value)) messages.push(`Prop "${propName}" ${optionName} must be a function.`);
283
415
  }
284
416
  }
285
417
  }
286
418
  function extractRuntimeProp(node) {
287
419
  if (_babel_types.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
420
+ if (isPropCall(node)) return extractPropCall(node);
288
421
  if (_babel_types.isObjectExpression(node)) {
289
422
  const typeNode = getObjectProperty(node, "type");
290
423
  const attrNode = getObjectProperty(node, "attr");
291
424
  const reflectNode = getObjectProperty(node, "reflect");
292
425
  const defaultNode = getObjectProperty(node, "default");
426
+ const serializeNode = getObjectProperty(node, "serialize");
427
+ const deserializeNode = getObjectProperty(node, "deserialize");
293
428
  const prop = { type: _babel_types.isIdentifier(typeNode) ? typeFromConstructorName(typeNode.name) : "unknown" };
294
429
  if (attrNode) {
295
430
  const attr = staticValue(attrNode);
@@ -302,16 +437,68 @@ function extractRuntimeProp(node) {
302
437
  if (defaultNode) {
303
438
  if (!_babel_types.isFunctionExpression(defaultNode) && !_babel_types.isArrowFunctionExpression(defaultNode)) prop.default = staticValue(defaultNode);
304
439
  }
440
+ if (serializeNode) prop.serialize = true;
441
+ if (deserializeNode) prop.deserialize = true;
442
+ const values = extractStaticStringArray(getObjectProperty(node, "values"));
443
+ if (values) prop.values = values;
305
444
  return prop;
306
445
  }
307
446
  return { type: "unknown" };
308
447
  }
448
+ function isPropCall(node) {
449
+ return _babel_types.isCallExpression(node) && _babel_types.isIdentifier(node.callee, { name: "prop" });
450
+ }
451
+ function validatePropCall(propName, node, messages) {
452
+ if (!isStaticStringArray(node.arguments[0]) && !isPropConstructorArgument(node.arguments[0])) messages.push(`Prop "${propName}" prop() first argument must be a static string array or prop constructor.`);
453
+ const optionsNode = node.arguments[1];
454
+ if (optionsNode && !_babel_types.isObjectExpression(optionsNode)) {
455
+ messages.push(`Prop "${propName}" prop() options must be an inline object literal.`);
456
+ return;
457
+ }
458
+ if (_babel_types.isObjectExpression(optionsNode)) validatePropOptions(propName, optionsNode, messages);
459
+ }
460
+ function extractPropCall(node) {
461
+ var _extractStaticStringA;
462
+ const inputNode = node.arguments[0];
463
+ const optionsNode = node.arguments[1];
464
+ const prop = _babel_types.isObjectExpression(optionsNode) ? extractRuntimeProp(optionsNode) : { type: "string" };
465
+ if (isPropConstructorArgument(inputNode)) {
466
+ prop.type = typeFromConstructorName(inputNode.name);
467
+ if (inputNode.name === "Boolean") {
468
+ var _prop$default, _prop$reflect;
469
+ (_prop$default = prop.default) !== null && _prop$default !== void 0 || (prop.default = false);
470
+ (_prop$reflect = prop.reflect) !== null && _prop$reflect !== void 0 || (prop.reflect = true);
471
+ }
472
+ return prop;
473
+ }
474
+ prop.type = "string";
475
+ prop.values = (_extractStaticStringA = extractStaticStringArray(node.arguments[0])) !== null && _extractStaticStringA !== void 0 ? _extractStaticStringA : [];
476
+ return prop;
477
+ }
478
+ function isPropConstructorArgument(node) {
479
+ return _babel_types.isIdentifier(node) && isPropConstructorName(node.name);
480
+ }
481
+ function isStaticStringArray(node) {
482
+ return Boolean(extractStaticStringArray(node));
483
+ }
484
+ function extractStaticStringArray(node) {
485
+ if (!_babel_types.isArrayExpression(node)) return void 0;
486
+ const values = [];
487
+ for (const item of node.elements) {
488
+ if (!_babel_types.isStringLiteral(item)) return void 0;
489
+ values.push(item.value);
490
+ }
491
+ return values;
492
+ }
309
493
  function isPropConstructorName(name) {
310
- return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array";
494
+ return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array" || name === "Function";
311
495
  }
312
496
  function isExplicitUndefined(node) {
313
497
  return _babel_types.isIdentifier(node) && node.name === "undefined";
314
498
  }
499
+ function isFunctionLikeReference(node) {
500
+ return _babel_types.isFunctionExpression(node) || _babel_types.isArrowFunctionExpression(node) || _babel_types.isIdentifier(node);
501
+ }
315
502
  function typeFromConstructorName(name) {
316
503
  switch (name) {
317
504
  case "String": return "string";
@@ -319,6 +506,7 @@ function typeFromConstructorName(name) {
319
506
  case "Boolean": return "boolean";
320
507
  case "Object": return "object";
321
508
  case "Array": return "array";
509
+ case "Function": return "function";
322
510
  default: return "unknown";
323
511
  }
324
512
  }
@@ -326,23 +514,27 @@ function typeFromConstructorName(name) {
326
514
  //#region packages/web-c/component-analyzer/src/extractSetup.ts
327
515
  function extractSetupMeta(setup) {
328
516
  const events = {};
517
+ const methods = {};
329
518
  const slots = {};
330
519
  const hostAttributes = [];
331
520
  const cssParts = [];
332
521
  if (!setup || _babel_types.isSpreadElement(setup) || _babel_types.isArgumentPlaceholder(setup)) return {
333
522
  events,
523
+ methods,
334
524
  slots,
335
525
  hostAttributes,
336
526
  cssParts
337
527
  };
338
528
  walk(setup, (node) => {
339
529
  extractEmit(node, events);
530
+ extractExpose(node, methods);
340
531
  extractSlot(node, slots);
341
532
  extractHostAttributes(node, hostAttributes);
342
533
  extractCssParts(node, cssParts);
343
534
  });
344
535
  return {
345
536
  events,
537
+ methods,
346
538
  slots,
347
539
  hostAttributes: uniqueSorted(hostAttributes),
348
540
  cssParts: uniqueSorted(cssParts)
@@ -350,13 +542,21 @@ function extractSetupMeta(setup) {
350
542
  }
351
543
  function extractEmit(node, events) {
352
544
  if (!_babel_types.isCallExpression(node)) return;
353
- if (!_babel_types.isIdentifier(node.callee, { name: "emit" })) return;
354
- const first = node.arguments[0];
355
- if (!_babel_types.isStringLiteral(first)) return;
356
- const eventName = first.value;
357
- events[eventName] || (events[eventName] = {});
358
- const detailNode = node.arguments[1];
359
- if (_babel_types.isObjectExpression(detailNode)) events[eventName].detail = inferDetail(detailNode);
545
+ const emitKey = getEmitKey(node.callee);
546
+ if (!emitKey) return;
547
+ events[emitKey] || (events[emitKey] = createComponentEvent(emitKey));
548
+ const detailNode = node.arguments[0];
549
+ if (_babel_types.isObjectExpression(detailNode)) events[emitKey].detail = inferDetail(detailNode);
550
+ }
551
+ function getEmitKey(callee) {
552
+ if (_babel_types.isMemberExpression(callee)) {
553
+ if (_babel_types.isIdentifier(callee.object, { name: "emit" }) && !callee.computed) return getMemberPropertyName(callee.property);
554
+ if (_babel_types.isMemberExpression(callee.object) && _babel_types.isIdentifier(callee.object.property, { name: "emit" }) && !callee.computed) return getMemberPropertyName(callee.property);
555
+ }
556
+ }
557
+ function getMemberPropertyName(property) {
558
+ if (_babel_types.isIdentifier(property)) return property.name;
559
+ if (_babel_types.isStringLiteral(property)) return property.value;
360
560
  }
361
561
  function inferDetail(node) {
362
562
  const result = {};
@@ -381,9 +581,111 @@ function extractSlot(node, slots) {
381
581
  var _getJSXStringAttribut;
382
582
  if (!_babel_types.isJSXElement(node)) return;
383
583
  const name = node.openingElement.name;
384
- if (!_babel_types.isJSXIdentifier(name, { name: "Slot" })) return;
584
+ if (!_babel_types.isJSXIdentifier(name, { name: "Slot" }) && !_babel_types.isJSXIdentifier(name, { name: "slot" })) return;
385
585
  const slotName = (_getJSXStringAttribut = getJSXStringAttribute(node, "name")) !== null && _getJSXStringAttribut !== void 0 ? _getJSXStringAttribut : "default";
386
- slots[slotName] || (slots[slotName] = {});
586
+ slots[slotName] || (slots[slotName] = { name: slotName });
587
+ }
588
+ function extractExpose(node, methods) {
589
+ if (!_babel_types.isCallExpression(node)) return;
590
+ if (!isExposeCallee(node.callee)) return;
591
+ const first = node.arguments[0];
592
+ if (!_babel_types.isObjectExpression(first)) return;
593
+ for (const member of first.properties) {
594
+ if (!_babel_types.isObjectMethod(member) && !_babel_types.isObjectProperty(member)) continue;
595
+ const name = getObjectKey(member.key);
596
+ if (!name) continue;
597
+ methods[name] = extractMethod(member, name);
598
+ }
599
+ }
600
+ function extractMethod(member, name) {
601
+ var _unwrapPromiseType, _formatTsType;
602
+ const fn = _babel_types.isObjectMethod(member) ? member : _babel_types.isFunctionExpression(member.value) || _babel_types.isArrowFunctionExpression(member.value) ? member.value : void 0;
603
+ if (!fn) return { name };
604
+ const returnType = _babel_types.isTSTypeAnnotation(fn.returnType) ? fn.returnType.typeAnnotation : void 0;
605
+ const normalizedReturn = fn.async ? (_unwrapPromiseType = unwrapPromiseType(returnType)) !== null && _unwrapPromiseType !== void 0 ? _unwrapPromiseType : returnType : returnType;
606
+ return {
607
+ name,
608
+ parameters: fn.params.map((param, index) => extractMethodParameter(param, index)),
609
+ returns: (_formatTsType = formatTsType(normalizedReturn)) !== null && _formatTsType !== void 0 ? _formatTsType : "unknown",
610
+ async: fn.async
611
+ };
612
+ }
613
+ function extractMethodParameter(param, index) {
614
+ var _formatTsType4;
615
+ if (_babel_types.isTSParameterProperty(param)) return extractMethodParameter(param.parameter, index);
616
+ if (_babel_types.isAssignmentPattern(param)) {
617
+ var _formatTsType2;
618
+ return {
619
+ name: _babel_types.isIdentifier(param.left) ? param.left.name : `arg${index}`,
620
+ type: (_formatTsType2 = formatTsType(getPatternTypeAnnotation(param.left))) !== null && _formatTsType2 !== void 0 ? _formatTsType2 : inferExpressionType(param.right),
621
+ optional: true
622
+ };
623
+ }
624
+ if (_babel_types.isRestElement(param)) {
625
+ var _ref, _formatTsType3;
626
+ return {
627
+ name: _babel_types.isIdentifier(param.argument) ? param.argument.name : `args${index}`,
628
+ type: (_ref = (_formatTsType3 = formatTsType(getPatternTypeAnnotation(param))) !== null && _formatTsType3 !== void 0 ? _formatTsType3 : formatTsType(getPatternTypeAnnotation(param.argument))) !== null && _ref !== void 0 ? _ref : "unknown[]",
629
+ optional: false,
630
+ rest: true
631
+ };
632
+ }
633
+ return {
634
+ name: _babel_types.isIdentifier(param) ? param.name : `arg${index}`,
635
+ type: (_formatTsType4 = formatTsType(getPatternTypeAnnotation(param))) !== null && _formatTsType4 !== void 0 ? _formatTsType4 : "unknown",
636
+ optional: Boolean(_babel_types.isIdentifier(param) && param.optional)
637
+ };
638
+ }
639
+ function getPatternTypeAnnotation(node) {
640
+ if (_babel_types.isIdentifier(node) || _babel_types.isObjectPattern(node) || _babel_types.isArrayPattern(node) || _babel_types.isRestElement(node)) return _babel_types.isTSTypeAnnotation(node.typeAnnotation) ? node.typeAnnotation.typeAnnotation : void 0;
641
+ }
642
+ function unwrapPromiseType(node) {
643
+ if (_babel_types.isTSTypeReference(node) && _babel_types.isIdentifier(node.typeName, { name: "Promise" })) {
644
+ var _node$typeParameters;
645
+ return (_node$typeParameters = node.typeParameters) === null || _node$typeParameters === void 0 ? void 0 : _node$typeParameters.params[0];
646
+ }
647
+ }
648
+ function formatTsType(node) {
649
+ if (!node) return void 0;
650
+ if (_babel_types.isTSStringKeyword(node)) return "string";
651
+ if (_babel_types.isTSNumberKeyword(node)) return "number";
652
+ if (_babel_types.isTSBooleanKeyword(node)) return "boolean";
653
+ if (_babel_types.isTSVoidKeyword(node)) return "void";
654
+ if (_babel_types.isTSUnknownKeyword(node)) return "unknown";
655
+ if (_babel_types.isTSAnyKeyword(node)) return "any";
656
+ if (_babel_types.isTSNullKeyword(node)) return "null";
657
+ if (_babel_types.isTSArrayType(node)) {
658
+ var _formatTsType5;
659
+ return `${(_formatTsType5 = formatTsType(node.elementType)) !== null && _formatTsType5 !== void 0 ? _formatTsType5 : "unknown"}[]`;
660
+ }
661
+ if (_babel_types.isTSUnionType(node)) return node.types.map((type) => {
662
+ var _formatTsType6;
663
+ return (_formatTsType6 = formatTsType(type)) !== null && _formatTsType6 !== void 0 ? _formatTsType6 : "unknown";
664
+ }).join(" | ");
665
+ if (_babel_types.isTSLiteralType(node)) return staticLiteralType(node.literal);
666
+ if (_babel_types.isTSTypeReference(node)) {
667
+ var _node$typeParameters2;
668
+ const name = formatEntityName(node.typeName);
669
+ const params = (_node$typeParameters2 = node.typeParameters) === null || _node$typeParameters2 === void 0 ? void 0 : _node$typeParameters2.params;
670
+ return (params === null || params === void 0 ? void 0 : params.length) ? `${name}<${params.map((type) => {
671
+ var _formatTsType7;
672
+ return (_formatTsType7 = formatTsType(type)) !== null && _formatTsType7 !== void 0 ? _formatTsType7 : "unknown";
673
+ }).join(", ")}>` : name;
674
+ }
675
+ return "unknown";
676
+ }
677
+ function formatEntityName(name) {
678
+ return _babel_types.isIdentifier(name) ? name.name : `${formatEntityName(name.left)}.${name.right.name}`;
679
+ }
680
+ function staticLiteralType(node) {
681
+ if (_babel_types.isStringLiteral(node)) return JSON.stringify(node.value);
682
+ if (_babel_types.isNumericLiteral(node)) return String(node.value);
683
+ if (_babel_types.isBooleanLiteral(node)) return String(node.value);
684
+ return "unknown";
685
+ }
686
+ function isExposeCallee(callee) {
687
+ if (_babel_types.isIdentifier(callee, { name: "expose" })) return true;
688
+ return _babel_types.isMemberExpression(callee) && _babel_types.isIdentifier(callee.property, { name: "expose" });
387
689
  }
388
690
  function extractHostAttributes(node, hostAttributes) {
389
691
  if (!_babel_types.isJSXElement(node)) return;
@@ -497,12 +799,14 @@ function inferType(node) {
497
799
  //#endregion
498
800
  //#region packages/web-c/component-analyzer/src/merge.ts
499
801
  function buildComponentRecord(options) {
500
- const { file, call, runtimeProps, runtimePropsDiagnostics, typeProps, setupMeta, inlineMeta, shadow } = options;
802
+ const { file, call, runtimeProps, runtimePropsDiagnostics, emits: declaredEvents, typeProps, setupMeta, inlineMeta, shadow, formAssociated } = options;
501
803
  const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
502
- const events = mergeEvents(setupMeta.events, inlineMeta.events);
804
+ const events = mergeEvents(declaredEvents, setupMeta.events, inlineMeta.events);
805
+ const methods = mergeMethods(setupMeta.methods, inlineMeta.methods);
806
+ const models = inlineMeta.models === void 0 ? inferModels(props, events) : normalizeModels(inlineMeta.models);
503
807
  const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
504
808
  const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
505
- const cssVars = unique(toStringArray(inlineMeta.cssVars));
809
+ const cssVars = toCssVarsRecord(inlineMeta.cssVars);
506
810
  const hostAttributes = unique(setupMeta.hostAttributes);
507
811
  const restMeta = stripKnownMetaFields(inlineMeta);
508
812
  return {
@@ -514,17 +818,52 @@ function buildComponentRecord(options) {
514
818
  runtimeProps,
515
819
  runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
516
820
  events,
821
+ methods,
822
+ models,
517
823
  slots,
518
824
  hostAttributes,
519
825
  cssParts,
520
826
  cssVars,
521
827
  description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
522
- meta: shadow !== void 0 || restMeta ? {
828
+ meta: shadow !== void 0 || formAssociated !== void 0 || restMeta ? {
523
829
  ...restMeta,
524
- shadow
830
+ shadow,
831
+ formAssociated
525
832
  } : void 0
526
833
  };
527
834
  }
835
+ function normalizeModels(value) {
836
+ if (!Array.isArray(value)) return void 0;
837
+ const models = [];
838
+ for (const item of value) {
839
+ if (!item || typeof item !== "object") continue;
840
+ const record = item;
841
+ if (typeof record.prop !== "string" || typeof record.event !== "string") continue;
842
+ models.push({
843
+ prop: record.prop,
844
+ event: record.event,
845
+ eventPath: typeof record.eventPath === "string" ? record.eventPath : void 0
846
+ });
847
+ }
848
+ return models.length ? models : void 0;
849
+ }
850
+ function inferModels(props, events) {
851
+ const models = [];
852
+ for (const prop of Object.keys(props)) {
853
+ var _event$name, _event$key;
854
+ const eventKey = `${prop}Change`;
855
+ const event = events[eventKey];
856
+ if (!(event === null || event === void 0 ? void 0 : event.detail) || !Object.prototype.hasOwnProperty.call(event.detail, prop)) continue;
857
+ const eventName = (_event$name = event.name) !== null && _event$name !== void 0 ? _event$name : toKebabCase((_event$key = event.key) !== null && _event$key !== void 0 ? _event$key : eventKey);
858
+ if (eventName !== `${toKebabCase(prop)}-change`) continue;
859
+ models.push({
860
+ prop,
861
+ event: eventName,
862
+ eventPath: `detail.${prop}`
863
+ });
864
+ }
865
+ return models.length ? models : void 0;
866
+ }
528
867
  function mergeProps(runtimeProps, typeProps, metaProps) {
529
868
  const names = unique([
530
869
  ...Object.keys(runtimeProps),
@@ -533,40 +872,104 @@ function mergeProps(runtimeProps, typeProps, metaProps) {
533
872
  ]);
534
873
  const result = {};
535
874
  for (const name of names) {
536
- var _typeProps$name, _runtimeProps$name, _metaProps$name, _ref, _rp$type, _tp$description, _rp$default, _rp$reflect, _rp$attr;
875
+ var _typeProps$name, _runtimeProps$name, _metaProps$name, _ref, _rp$type, _rp$values, _tp$description, _rp$default, _rp$reflect, _rp$attr, _rp$serialize, _rp$deserialize;
537
876
  const tp = (_typeProps$name = typeProps[name]) !== null && _typeProps$name !== void 0 ? _typeProps$name : {};
538
877
  const rp = (_runtimeProps$name = runtimeProps[name]) !== null && _runtimeProps$name !== void 0 ? _runtimeProps$name : {};
539
878
  const mp = (_metaProps$name = metaProps === null || metaProps === void 0 ? void 0 : metaProps[name]) !== null && _metaProps$name !== void 0 ? _metaProps$name : {};
540
879
  result[name] = {
541
880
  type: (_ref = (_rp$type = rp.type) !== null && _rp$type !== void 0 ? _rp$type : tp.type) !== null && _ref !== void 0 ? _ref : "unknown",
542
881
  required: tp.required,
543
- values: tp.values,
882
+ values: (_rp$values = rp.values) !== null && _rp$values !== void 0 ? _rp$values : tp.values,
544
883
  description: (_tp$description = tp.description) !== null && _tp$description !== void 0 ? _tp$description : mp.description,
545
884
  default: (_rp$default = rp.default) !== null && _rp$default !== void 0 ? _rp$default : mp.default,
546
885
  reflect: (_rp$reflect = rp.reflect) !== null && _rp$reflect !== void 0 ? _rp$reflect : mp.reflect,
547
- attr: (_rp$attr = rp.attr) !== null && _rp$attr !== void 0 ? _rp$attr : mp.attr
886
+ attr: (_rp$attr = rp.attr) !== null && _rp$attr !== void 0 ? _rp$attr : mp.attr,
887
+ serialize: (_rp$serialize = rp.serialize) !== null && _rp$serialize !== void 0 ? _rp$serialize : mp.serialize,
888
+ deserialize: (_rp$deserialize = rp.deserialize) !== null && _rp$deserialize !== void 0 ? _rp$deserialize : mp.deserialize
548
889
  };
549
890
  }
550
891
  return result;
551
892
  }
552
- function mergeEvents(inferred, explicit) {
893
+ function mergeEvents(declared, inferred, explicit) {
894
+ const result = {};
895
+ for (const [key, value] of Object.entries(declared)) result[key] = mergeEvent(value, inferred[key]);
896
+ for (const [key, value] of Object.entries(explicit !== null && explicit !== void 0 ? explicit : {})) if (result[key]) result[key] = normalizeExplicitEvent(key, value, result[key]);
897
+ return result;
898
+ }
899
+ function mergeEvent(primary, fallback) {
900
+ var _primary$key, _primary$name, _primary$reactName, _primary$detail, _primary$bubbles, _primary$composed, _primary$cancelable, _primary$description;
553
901
  return {
554
- ...inferred,
555
- ...explicit !== null && explicit !== void 0 ? explicit : {}
902
+ key: (_primary$key = primary.key) !== null && _primary$key !== void 0 ? _primary$key : fallback === null || fallback === void 0 ? void 0 : fallback.key,
903
+ name: (_primary$name = primary.name) !== null && _primary$name !== void 0 ? _primary$name : fallback === null || fallback === void 0 ? void 0 : fallback.name,
904
+ reactName: (_primary$reactName = primary.reactName) !== null && _primary$reactName !== void 0 ? _primary$reactName : fallback === null || fallback === void 0 ? void 0 : fallback.reactName,
905
+ detail: (_primary$detail = primary.detail) !== null && _primary$detail !== void 0 ? _primary$detail : fallback === null || fallback === void 0 ? void 0 : fallback.detail,
906
+ bubbles: (_primary$bubbles = primary.bubbles) !== null && _primary$bubbles !== void 0 ? _primary$bubbles : fallback === null || fallback === void 0 ? void 0 : fallback.bubbles,
907
+ composed: (_primary$composed = primary.composed) !== null && _primary$composed !== void 0 ? _primary$composed : fallback === null || fallback === void 0 ? void 0 : fallback.composed,
908
+ cancelable: (_primary$cancelable = primary.cancelable) !== null && _primary$cancelable !== void 0 ? _primary$cancelable : fallback === null || fallback === void 0 ? void 0 : fallback.cancelable,
909
+ description: (_primary$description = primary.description) !== null && _primary$description !== void 0 ? _primary$description : fallback === null || fallback === void 0 ? void 0 : fallback.description
910
+ };
911
+ }
912
+ function normalizeExplicitEvent(key, value, base) {
913
+ var _value$key, _value$name, _value$reactName, _value$detail, _value$bubbles, _value$composed, _value$cancelable, _value$description;
914
+ const fallback = base !== null && base !== void 0 ? base : createComponentEvent(key);
915
+ return {
916
+ key: (_value$key = value.key) !== null && _value$key !== void 0 ? _value$key : fallback.key,
917
+ name: (_value$name = value.name) !== null && _value$name !== void 0 ? _value$name : fallback.name,
918
+ reactName: (_value$reactName = value.reactName) !== null && _value$reactName !== void 0 ? _value$reactName : fallback.reactName,
919
+ detail: (_value$detail = value.detail) !== null && _value$detail !== void 0 ? _value$detail : fallback.detail,
920
+ bubbles: (_value$bubbles = value.bubbles) !== null && _value$bubbles !== void 0 ? _value$bubbles : fallback.bubbles,
921
+ composed: (_value$composed = value.composed) !== null && _value$composed !== void 0 ? _value$composed : fallback.composed,
922
+ cancelable: (_value$cancelable = value.cancelable) !== null && _value$cancelable !== void 0 ? _value$cancelable : fallback.cancelable,
923
+ description: (_value$description = value.description) !== null && _value$description !== void 0 ? _value$description : fallback.description
556
924
  };
557
925
  }
926
+ function mergeMethods(inferred, explicit) {
927
+ const result = { ...inferred };
928
+ if (Array.isArray(explicit)) {
929
+ for (const name of explicit) if (typeof name === "string") result[name] = { name };
930
+ }
931
+ return result;
932
+ }
558
933
  function mergeSlots(inferred, explicit) {
934
+ if (Array.isArray(explicit)) {
935
+ const result = { ...inferred };
936
+ for (const name of explicit) if (typeof name === "string") result[name] = { name };
937
+ return result;
938
+ }
939
+ if (!explicit || typeof explicit !== "object") return { ...inferred };
559
940
  return {
560
941
  ...inferred,
561
- ...explicit !== null && explicit !== void 0 ? explicit : {}
942
+ ...explicit
562
943
  };
563
944
  }
564
945
  function toStringArray(value) {
565
946
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
566
947
  }
948
+ function toCssVarsRecord(value) {
949
+ if (Array.isArray(value)) {
950
+ const result = {};
951
+ for (const item of value) if (typeof item === "string") result[item] = { name: item };
952
+ return result;
953
+ }
954
+ if (value && typeof value === "object") {
955
+ const result = {};
956
+ for (const [name, item] of Object.entries(value)) if (item && typeof item === "object") {
957
+ const description = item.description;
958
+ result[name] = {
959
+ name,
960
+ description: typeof description === "string" ? description : void 0
961
+ };
962
+ } else result[name] = { name };
963
+ return result;
964
+ }
965
+ return {};
966
+ }
567
967
  function unique(values) {
568
968
  return Array.from(new Set(values)).sort();
569
969
  }
970
+ function toKebabCase(value) {
971
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
972
+ }
570
973
  function stripKnownMetaFields(meta) {
571
974
  const rest = { ...meta };
572
975
  delete rest.description;
@@ -576,6 +979,9 @@ function stripKnownMetaFields(meta) {
576
979
  delete rest.cssVars;
577
980
  delete rest.cssParts;
578
981
  delete rest.shadow;
982
+ delete rest.formAssociated;
983
+ delete rest.methods;
984
+ delete rest.models;
579
985
  return Object.keys(rest).length ? rest : void 0;
580
986
  }
581
987
  //#endregion
@@ -588,8 +994,9 @@ function analyzeFile(options) {
588
994
  const ast = parseSource(code, file);
589
995
  const calls = extractDefineElementCalls(ast);
590
996
  const localPropTypes = collectLocalPropTypes(ast);
997
+ const localSetupBindings = collectLocalSetupBindings(ast);
591
998
  for (const call of calls) {
592
- var _localPropTypes$get, _shadowOption$shadow;
999
+ var _localPropTypes$get, _componentOptions$sha, _componentOptions$for;
593
1000
  const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
594
1001
  for (const message of runtimePropsDiagnostics) diagnostics.push({
595
1002
  level: "warning",
@@ -597,24 +1004,27 @@ function analyzeFile(options) {
597
1004
  message: `<${call.tag}> ${message}`
598
1005
  });
599
1006
  const runtimeProps = extractRuntimeProps(call.options);
600
- const shadowOption = extractShadowOption(call.options);
1007
+ const emits = extractEmits(call.options);
1008
+ const componentOptions = extractComponentOptions(call.options);
601
1009
  const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
602
1010
  if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
603
1011
  level: "warning",
604
1012
  file,
605
1013
  message: `Cannot resolve local props type "${call.propsTypeName}".`
606
1014
  });
607
- const setupMeta = extractSetupMeta(call.setup);
1015
+ const setupMeta = extractSetupMeta(resolveSetupBinding(call.setup, localSetupBindings));
608
1016
  const inlineMeta = extractInlineMeta(call.options);
609
1017
  components.push(buildComponentRecord({
610
1018
  file,
611
1019
  call,
612
1020
  runtimeProps,
613
1021
  runtimePropsDiagnostics,
1022
+ emits,
614
1023
  typeProps,
615
1024
  setupMeta,
616
1025
  inlineMeta,
617
- shadow: (_shadowOption$shadow = shadowOption.shadow) !== null && _shadowOption$shadow !== void 0 ? _shadowOption$shadow : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0
1026
+ shadow: (_componentOptions$sha = componentOptions.shadow) !== null && _componentOptions$sha !== void 0 ? _componentOptions$sha : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0,
1027
+ formAssociated: (_componentOptions$for = componentOptions.formAssociated) !== null && _componentOptions$for !== void 0 ? _componentOptions$for : typeof inlineMeta.formAssociated === "boolean" ? inlineMeta.formAssociated : void 0
618
1028
  }));
619
1029
  }
620
1030
  } catch (error) {
@@ -630,6 +1040,28 @@ function analyzeFile(options) {
630
1040
  diagnostics
631
1041
  };
632
1042
  }
1043
+ function collectLocalSetupBindings(ast) {
1044
+ const bindings = /* @__PURE__ */ new Map();
1045
+ for (const node of ast.program.body) {
1046
+ if (_babel_types.isFunctionDeclaration(node) && node.id) {
1047
+ bindings.set(node.id.name, node);
1048
+ continue;
1049
+ }
1050
+ if (!_babel_types.isVariableDeclaration(node)) continue;
1051
+ for (const declarator of node.declarations) {
1052
+ if (!_babel_types.isIdentifier(declarator.id) || !declarator.init) continue;
1053
+ if (_babel_types.isFunctionExpression(declarator.init) || _babel_types.isArrowFunctionExpression(declarator.init)) bindings.set(declarator.id.name, declarator.init);
1054
+ }
1055
+ }
1056
+ return bindings;
1057
+ }
1058
+ function resolveSetupBinding(setup, bindings) {
1059
+ if (_babel_types.isIdentifier(setup)) {
1060
+ var _bindings$get;
1061
+ return (_bindings$get = bindings.get(setup.name)) !== null && _bindings$get !== void 0 ? _bindings$get : setup;
1062
+ }
1063
+ return setup;
1064
+ }
633
1065
  function isGlobalUtilityType(name) {
634
1066
  return GLOBAL_UTILITY_TYPES.has(name);
635
1067
  }