@zeus-js/component-analyzer 0.1.0-beta.2 → 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.2
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,17 +181,145 @@ 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
308
+ function extractComponentOptions(options) {
309
+ if (!options) return {};
310
+ const result = {};
311
+ const shadowNode = getObjectProperty(options, "shadow");
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;
322
+ }
195
323
  function extractRuntimeProps(options) {
196
324
  if (!options) return {};
197
325
  const propsNode = getObjectProperty(options, "props");
@@ -205,13 +333,98 @@ function extractRuntimeProps(options) {
205
333
  }
206
334
  return props;
207
335
  }
336
+ function validateRuntimePropsDefinition(options, optionsArgument) {
337
+ const messages = [];
338
+ if (optionsArgument && !_babel_types.isObjectExpression(optionsArgument)) {
339
+ messages.push("defineElement() options must be an inline object literal so component metadata can be analyzed.");
340
+ return messages;
341
+ }
342
+ if (!options) return messages;
343
+ for (const member of options.properties) if (!_babel_types.isObjectProperty(member) || member.computed) messages.push("defineElement() options cannot contain spreads, methods, or computed keys in component output builds.");
344
+ const propsNode = getObjectProperty(options, "props");
345
+ if (!propsNode) return messages;
346
+ if (!_babel_types.isObjectExpression(propsNode)) {
347
+ messages.push("defineElement() props must be an inline object literal in component output builds.");
348
+ return messages;
349
+ }
350
+ for (const member of propsNode.properties) {
351
+ if (!_babel_types.isObjectProperty(member) || member.computed) {
352
+ messages.push("defineElement() props cannot contain spreads, methods, or computed keys.");
353
+ continue;
354
+ }
355
+ const propName = getObjectKey(member.key);
356
+ if (!propName) {
357
+ messages.push("defineElement() contains a prop with an unsupported key.");
358
+ continue;
359
+ }
360
+ if (_babel_types.isIdentifier(member.value)) {
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);
366
+ continue;
367
+ }
368
+ if (!_babel_types.isObjectExpression(member.value)) {
369
+ messages.push(`Prop "${propName}" must use an inline prop options object, prop(values), or prop(Constructor).`);
370
+ continue;
371
+ }
372
+ validatePropOptions(propName, member.value, messages);
373
+ }
374
+ return messages;
375
+ }
376
+ function validatePropOptions(propName, options, messages) {
377
+ for (const member of options.properties) {
378
+ if (!_babel_types.isObjectProperty(member) || member.computed) {
379
+ messages.push(`Prop "${propName}" options cannot contain spreads, methods, or computed keys.`);
380
+ continue;
381
+ }
382
+ const optionName = getObjectKey(member.key);
383
+ if (!optionName) {
384
+ messages.push(`Prop "${propName}" contains an unsupported option key.`);
385
+ continue;
386
+ }
387
+ if (optionName === "type") {
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.`);
389
+ continue;
390
+ }
391
+ if (optionName === "attr") {
392
+ const value = staticValue(member.value);
393
+ if (value === void 0 && !isExplicitUndefined(member.value)) {
394
+ messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
395
+ continue;
396
+ }
397
+ if (value !== void 0 && value !== false && typeof value !== "string") messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
398
+ continue;
399
+ }
400
+ if (optionName === "reflect") {
401
+ const value = staticValue(member.value);
402
+ if (value === void 0 && !isExplicitUndefined(member.value)) {
403
+ messages.push(`Prop "${propName}" reflect must be a static boolean.`);
404
+ continue;
405
+ }
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.`);
415
+ }
416
+ }
417
+ }
208
418
  function extractRuntimeProp(node) {
209
419
  if (_babel_types.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
420
+ if (isPropCall(node)) return extractPropCall(node);
210
421
  if (_babel_types.isObjectExpression(node)) {
211
422
  const typeNode = getObjectProperty(node, "type");
212
423
  const attrNode = getObjectProperty(node, "attr");
213
424
  const reflectNode = getObjectProperty(node, "reflect");
214
425
  const defaultNode = getObjectProperty(node, "default");
426
+ const serializeNode = getObjectProperty(node, "serialize");
427
+ const deserializeNode = getObjectProperty(node, "deserialize");
215
428
  const prop = { type: _babel_types.isIdentifier(typeNode) ? typeFromConstructorName(typeNode.name) : "unknown" };
216
429
  if (attrNode) {
217
430
  const attr = staticValue(attrNode);
@@ -224,10 +437,68 @@ function extractRuntimeProp(node) {
224
437
  if (defaultNode) {
225
438
  if (!_babel_types.isFunctionExpression(defaultNode) && !_babel_types.isArrowFunctionExpression(defaultNode)) prop.default = staticValue(defaultNode);
226
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;
227
444
  return prop;
228
445
  }
229
446
  return { type: "unknown" };
230
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
+ }
493
+ function isPropConstructorName(name) {
494
+ return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array" || name === "Function";
495
+ }
496
+ function isExplicitUndefined(node) {
497
+ return _babel_types.isIdentifier(node) && node.name === "undefined";
498
+ }
499
+ function isFunctionLikeReference(node) {
500
+ return _babel_types.isFunctionExpression(node) || _babel_types.isArrowFunctionExpression(node) || _babel_types.isIdentifier(node);
501
+ }
231
502
  function typeFromConstructorName(name) {
232
503
  switch (name) {
233
504
  case "String": return "string";
@@ -235,6 +506,7 @@ function typeFromConstructorName(name) {
235
506
  case "Boolean": return "boolean";
236
507
  case "Object": return "object";
237
508
  case "Array": return "array";
509
+ case "Function": return "function";
238
510
  default: return "unknown";
239
511
  }
240
512
  }
@@ -242,23 +514,27 @@ function typeFromConstructorName(name) {
242
514
  //#region packages/web-c/component-analyzer/src/extractSetup.ts
243
515
  function extractSetupMeta(setup) {
244
516
  const events = {};
517
+ const methods = {};
245
518
  const slots = {};
246
519
  const hostAttributes = [];
247
520
  const cssParts = [];
248
521
  if (!setup || _babel_types.isSpreadElement(setup) || _babel_types.isArgumentPlaceholder(setup)) return {
249
522
  events,
523
+ methods,
250
524
  slots,
251
525
  hostAttributes,
252
526
  cssParts
253
527
  };
254
528
  walk(setup, (node) => {
255
529
  extractEmit(node, events);
530
+ extractExpose(node, methods);
256
531
  extractSlot(node, slots);
257
532
  extractHostAttributes(node, hostAttributes);
258
533
  extractCssParts(node, cssParts);
259
534
  });
260
535
  return {
261
536
  events,
537
+ methods,
262
538
  slots,
263
539
  hostAttributes: uniqueSorted(hostAttributes),
264
540
  cssParts: uniqueSorted(cssParts)
@@ -266,13 +542,21 @@ function extractSetupMeta(setup) {
266
542
  }
267
543
  function extractEmit(node, events) {
268
544
  if (!_babel_types.isCallExpression(node)) return;
269
- if (!_babel_types.isIdentifier(node.callee, { name: "emit" })) return;
270
- const first = node.arguments[0];
271
- if (!_babel_types.isStringLiteral(first)) return;
272
- const eventName = first.value;
273
- events[eventName] || (events[eventName] = {});
274
- const detailNode = node.arguments[1];
275
- 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;
276
560
  }
277
561
  function inferDetail(node) {
278
562
  const result = {};
@@ -297,9 +581,111 @@ function extractSlot(node, slots) {
297
581
  var _getJSXStringAttribut;
298
582
  if (!_babel_types.isJSXElement(node)) return;
299
583
  const name = node.openingElement.name;
300
- if (!_babel_types.isJSXIdentifier(name, { name: "Slot" })) return;
584
+ if (!_babel_types.isJSXIdentifier(name, { name: "Slot" }) && !_babel_types.isJSXIdentifier(name, { name: "slot" })) return;
301
585
  const slotName = (_getJSXStringAttribut = getJSXStringAttribute(node, "name")) !== null && _getJSXStringAttribut !== void 0 ? _getJSXStringAttribut : "default";
302
- 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" });
303
689
  }
304
690
  function extractHostAttributes(node, hostAttributes) {
305
691
  if (!_babel_types.isJSXElement(node)) return;
@@ -413,28 +799,71 @@ function inferType(node) {
413
799
  //#endregion
414
800
  //#region packages/web-c/component-analyzer/src/merge.ts
415
801
  function buildComponentRecord(options) {
416
- const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
802
+ const { file, call, runtimeProps, runtimePropsDiagnostics, emits: declaredEvents, typeProps, setupMeta, inlineMeta, shadow, formAssociated } = options;
417
803
  const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
418
- 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);
419
807
  const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
420
808
  const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
421
- const cssVars = unique(toStringArray(inlineMeta.cssVars));
809
+ const cssVars = toCssVarsRecord(inlineMeta.cssVars);
422
810
  const hostAttributes = unique(setupMeta.hostAttributes);
811
+ const restMeta = stripKnownMetaFields(inlineMeta);
423
812
  return {
424
813
  tag: call.tag,
425
814
  name: call.name,
426
815
  exportName: call.exportName,
427
816
  source: file,
428
817
  props,
818
+ runtimeProps,
819
+ runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
429
820
  events,
821
+ methods,
822
+ models,
430
823
  slots,
431
824
  hostAttributes,
432
825
  cssParts,
433
826
  cssVars,
434
827
  description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
435
- meta: stripKnownMetaFields(inlineMeta)
828
+ meta: shadow !== void 0 || formAssociated !== void 0 || restMeta ? {
829
+ ...restMeta,
830
+ shadow,
831
+ formAssociated
832
+ } : void 0
436
833
  };
437
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
+ }
438
867
  function mergeProps(runtimeProps, typeProps, metaProps) {
439
868
  const names = unique([
440
869
  ...Object.keys(runtimeProps),
@@ -443,40 +872,104 @@ function mergeProps(runtimeProps, typeProps, metaProps) {
443
872
  ]);
444
873
  const result = {};
445
874
  for (const name of names) {
446
- 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;
447
876
  const tp = (_typeProps$name = typeProps[name]) !== null && _typeProps$name !== void 0 ? _typeProps$name : {};
448
877
  const rp = (_runtimeProps$name = runtimeProps[name]) !== null && _runtimeProps$name !== void 0 ? _runtimeProps$name : {};
449
878
  const mp = (_metaProps$name = metaProps === null || metaProps === void 0 ? void 0 : metaProps[name]) !== null && _metaProps$name !== void 0 ? _metaProps$name : {};
450
879
  result[name] = {
451
880
  type: (_ref = (_rp$type = rp.type) !== null && _rp$type !== void 0 ? _rp$type : tp.type) !== null && _ref !== void 0 ? _ref : "unknown",
452
881
  required: tp.required,
453
- values: tp.values,
882
+ values: (_rp$values = rp.values) !== null && _rp$values !== void 0 ? _rp$values : tp.values,
454
883
  description: (_tp$description = tp.description) !== null && _tp$description !== void 0 ? _tp$description : mp.description,
455
884
  default: (_rp$default = rp.default) !== null && _rp$default !== void 0 ? _rp$default : mp.default,
456
885
  reflect: (_rp$reflect = rp.reflect) !== null && _rp$reflect !== void 0 ? _rp$reflect : mp.reflect,
457
- 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
458
889
  };
459
890
  }
460
891
  return result;
461
892
  }
462
- 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;
463
901
  return {
464
- ...inferred,
465
- ...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
466
924
  };
467
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
+ }
468
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 };
469
940
  return {
470
941
  ...inferred,
471
- ...explicit !== null && explicit !== void 0 ? explicit : {}
942
+ ...explicit
472
943
  };
473
944
  }
474
945
  function toStringArray(value) {
475
946
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
476
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
+ }
477
967
  function unique(values) {
478
968
  return Array.from(new Set(values)).sort();
479
969
  }
970
+ function toKebabCase(value) {
971
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
972
+ }
480
973
  function stripKnownMetaFields(meta) {
481
974
  const rest = { ...meta };
482
975
  delete rest.description;
@@ -485,6 +978,10 @@ function stripKnownMetaFields(meta) {
485
978
  delete rest.slots;
486
979
  delete rest.cssVars;
487
980
  delete rest.cssParts;
981
+ delete rest.shadow;
982
+ delete rest.formAssociated;
983
+ delete rest.methods;
984
+ delete rest.models;
488
985
  return Object.keys(rest).length ? rest : void 0;
489
986
  }
490
987
  //#endregion
@@ -497,24 +994,37 @@ function analyzeFile(options) {
497
994
  const ast = parseSource(code, file);
498
995
  const calls = extractDefineElementCalls(ast);
499
996
  const localPropTypes = collectLocalPropTypes(ast);
997
+ const localSetupBindings = collectLocalSetupBindings(ast);
500
998
  for (const call of calls) {
501
- var _localPropTypes$get;
999
+ var _localPropTypes$get, _componentOptions$sha, _componentOptions$for;
1000
+ const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
1001
+ for (const message of runtimePropsDiagnostics) diagnostics.push({
1002
+ level: "warning",
1003
+ file,
1004
+ message: `<${call.tag}> ${message}`
1005
+ });
502
1006
  const runtimeProps = extractRuntimeProps(call.options);
1007
+ const emits = extractEmits(call.options);
1008
+ const componentOptions = extractComponentOptions(call.options);
503
1009
  const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
504
1010
  if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
505
1011
  level: "warning",
506
1012
  file,
507
1013
  message: `Cannot resolve local props type "${call.propsTypeName}".`
508
1014
  });
509
- const setupMeta = extractSetupMeta(call.setup);
1015
+ const setupMeta = extractSetupMeta(resolveSetupBinding(call.setup, localSetupBindings));
510
1016
  const inlineMeta = extractInlineMeta(call.options);
511
1017
  components.push(buildComponentRecord({
512
1018
  file,
513
1019
  call,
514
1020
  runtimeProps,
1021
+ runtimePropsDiagnostics,
1022
+ emits,
515
1023
  typeProps,
516
1024
  setupMeta,
517
- inlineMeta
1025
+ inlineMeta,
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
518
1028
  }));
519
1029
  }
520
1030
  } catch (error) {
@@ -530,6 +1040,28 @@ function analyzeFile(options) {
530
1040
  diagnostics
531
1041
  };
532
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
+ }
533
1065
  function isGlobalUtilityType(name) {
534
1066
  return GLOBAL_UTILITY_TYPES.has(name);
535
1067
  }