@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,10 +1,10 @@
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
  **/
6
- import { parse } from "@babel/parser";
7
6
  import * as t from "@babel/types";
7
+ import { parse } from "@babel/parser";
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import fg from "fast-glob";
@@ -151,17 +151,145 @@ function uniqueSorted(values) {
151
151
  return Array.from(new Set(values)).sort();
152
152
  }
153
153
  //#endregion
154
+ //#region packages/web-c/component-analyzer/src/extractEmits.ts
155
+ function extractEmits(options) {
156
+ const emitsNode = options ? getObjectProperty(options, "emits") : void 0;
157
+ if (!t.isObjectExpression(emitsNode)) return {};
158
+ const events = {};
159
+ for (const member of emitsNode.properties) {
160
+ if (!t.isObjectProperty(member) || member.computed) continue;
161
+ const key = getObjectKey(member.key);
162
+ if (!key) continue;
163
+ events[key] = extractEventDefinition(key, member.value);
164
+ }
165
+ return events;
166
+ }
167
+ function createComponentEvent(key, detail) {
168
+ return {
169
+ key,
170
+ name: toKebabCase$1(key),
171
+ reactName: toReactEventProp(key),
172
+ detail,
173
+ bubbles: true,
174
+ composed: true,
175
+ cancelable: false
176
+ };
177
+ }
178
+ function extractEventDefinition(key, node) {
179
+ var _extractEventDetailTy;
180
+ const result = createComponentEvent(key);
181
+ if (!t.isCallExpression(node)) return result;
182
+ if (!t.isIdentifier(node.callee, { name: "event" })) return result;
183
+ result.detail = (_extractEventDetailTy = extractEventDetailType(node)) !== null && _extractEventDetailTy !== void 0 ? _extractEventDetailTy : result.detail;
184
+ const first = node.arguments[0];
185
+ if (t.isStringLiteral(first)) {
186
+ result.name = first.value;
187
+ return result;
188
+ }
189
+ if (t.isObjectExpression(first)) {
190
+ const name = getObjectProperty(first, "name");
191
+ const bubbles = getObjectProperty(first, "bubbles");
192
+ const composed = getObjectProperty(first, "composed");
193
+ const cancelable = getObjectProperty(first, "cancelable");
194
+ const nameValue = staticValue(name);
195
+ const bubblesValue = staticValue(bubbles);
196
+ const composedValue = staticValue(composed);
197
+ const cancelableValue = staticValue(cancelable);
198
+ if (typeof nameValue === "string") result.name = nameValue;
199
+ if (typeof bubblesValue === "boolean") result.bubbles = bubblesValue;
200
+ if (typeof composedValue === "boolean") result.composed = composedValue;
201
+ if (typeof cancelableValue === "boolean") result.cancelable = cancelableValue;
202
+ }
203
+ return result;
204
+ }
205
+ function extractEventDetailType(node) {
206
+ var _node$typeParameters;
207
+ const first = (_node$typeParameters = node.typeParameters) === null || _node$typeParameters === void 0 ? void 0 : _node$typeParameters.params[0];
208
+ if (!t.isTSTypeLiteral(first)) return void 0;
209
+ const detail = {};
210
+ for (const member of first.members) {
211
+ var _member$typeAnnotatio;
212
+ if (!t.isTSPropertySignature(member)) continue;
213
+ const key = getObjectKey(member.key);
214
+ if (!key) continue;
215
+ detail[key] = inferTsType((_member$typeAnnotatio = member.typeAnnotation) === null || _member$typeAnnotatio === void 0 ? void 0 : _member$typeAnnotatio.typeAnnotation);
216
+ }
217
+ return Object.keys(detail).length > 0 ? detail : void 0;
218
+ }
219
+ function inferTsType(node) {
220
+ if (!node) return "unknown";
221
+ if (t.isTSStringKeyword(node)) return "string";
222
+ if (t.isTSNumberKeyword(node)) return "number";
223
+ if (t.isTSBooleanKeyword(node)) return "boolean";
224
+ if (t.isTSObjectKeyword(node) || t.isTSTypeLiteral(node)) return "object";
225
+ if (t.isTSArrayType(node) || t.isTSTupleType(node)) return "array";
226
+ if (t.isTSFunctionType(node)) return "function";
227
+ if (t.isTSTypeReference(node)) return inferTsTypeReference(node);
228
+ return "unknown";
229
+ }
230
+ function inferTsTypeReference(node) {
231
+ const name = t.isIdentifier(node.typeName) ? node.typeName.name : void 0;
232
+ switch (name) {
233
+ case "String": return "string";
234
+ case "Number": return "number";
235
+ case "Boolean": return "boolean";
236
+ case "Array":
237
+ case "ReadonlyArray": return "array";
238
+ case "Function": return "function";
239
+ case "Record": return "object";
240
+ default: return name !== null && name !== void 0 ? name : "unknown";
241
+ }
242
+ }
243
+ function toKebabCase$1(value) {
244
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
245
+ }
246
+ function toReactEventProp(value) {
247
+ return `on${value.split("-").filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("")}`;
248
+ }
249
+ //#endregion
154
250
  //#region packages/web-c/component-analyzer/src/extractMeta.ts
155
251
  function extractInlineMeta(options) {
156
252
  if (!options) return {};
157
253
  const metaNode = getObjectProperty(options, "meta");
158
- if (!t.isObjectExpression(metaNode)) return {};
159
- const value = staticValue(metaNode);
160
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
161
- return value;
254
+ const result = {};
255
+ if (t.isObjectExpression(metaNode)) {
256
+ const value = staticValue(metaNode);
257
+ if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(result, value);
258
+ }
259
+ assignTopLevelStaticValue(options, result, "slots");
260
+ assignTopLevelStaticValue(options, result, "parts");
261
+ assignTopLevelStaticValue(options, result, "cssVars");
262
+ assignTopLevelStaticValue(options, result, "methods");
263
+ assignTopLevelStaticValue(options, result, "models");
264
+ return result;
265
+ }
266
+ function assignTopLevelStaticValue(options, result, key) {
267
+ const node = getObjectProperty(options, key);
268
+ if (!node) return;
269
+ const value = staticValue(node);
270
+ if (key === "parts") {
271
+ result.cssParts = Array.isArray(value) ? value.filter((item) => typeof item === "string") : result.cssParts;
272
+ return;
273
+ }
274
+ result[key] = value;
162
275
  }
163
276
  //#endregion
164
277
  //#region packages/web-c/component-analyzer/src/extractProps.ts
278
+ function extractComponentOptions(options) {
279
+ if (!options) return {};
280
+ const result = {};
281
+ const shadowNode = getObjectProperty(options, "shadow");
282
+ if (shadowNode) {
283
+ const value = staticValue(shadowNode);
284
+ if (typeof value === "boolean") result.shadow = value;
285
+ }
286
+ const formAssociatedNode = getObjectProperty(options, "formAssociated");
287
+ if (formAssociatedNode) {
288
+ const value = staticValue(formAssociatedNode);
289
+ if (typeof value === "boolean") result.formAssociated = value;
290
+ }
291
+ return result;
292
+ }
165
293
  function extractRuntimeProps(options) {
166
294
  if (!options) return {};
167
295
  const propsNode = getObjectProperty(options, "props");
@@ -175,13 +303,98 @@ function extractRuntimeProps(options) {
175
303
  }
176
304
  return props;
177
305
  }
306
+ function validateRuntimePropsDefinition(options, optionsArgument) {
307
+ const messages = [];
308
+ if (optionsArgument && !t.isObjectExpression(optionsArgument)) {
309
+ messages.push("defineElement() options must be an inline object literal so component metadata can be analyzed.");
310
+ return messages;
311
+ }
312
+ if (!options) return messages;
313
+ for (const member of options.properties) if (!t.isObjectProperty(member) || member.computed) messages.push("defineElement() options cannot contain spreads, methods, or computed keys in component output builds.");
314
+ const propsNode = getObjectProperty(options, "props");
315
+ if (!propsNode) return messages;
316
+ if (!t.isObjectExpression(propsNode)) {
317
+ messages.push("defineElement() props must be an inline object literal in component output builds.");
318
+ return messages;
319
+ }
320
+ for (const member of propsNode.properties) {
321
+ if (!t.isObjectProperty(member) || member.computed) {
322
+ messages.push("defineElement() props cannot contain spreads, methods, or computed keys.");
323
+ continue;
324
+ }
325
+ const propName = getObjectKey(member.key);
326
+ if (!propName) {
327
+ messages.push("defineElement() contains a prop with an unsupported key.");
328
+ continue;
329
+ }
330
+ if (t.isIdentifier(member.value)) {
331
+ 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.`);
332
+ continue;
333
+ }
334
+ if (isPropCall(member.value)) {
335
+ validatePropCall(propName, member.value, messages);
336
+ continue;
337
+ }
338
+ if (!t.isObjectExpression(member.value)) {
339
+ messages.push(`Prop "${propName}" must use an inline prop options object, prop(values), or prop(Constructor).`);
340
+ continue;
341
+ }
342
+ validatePropOptions(propName, member.value, messages);
343
+ }
344
+ return messages;
345
+ }
346
+ function validatePropOptions(propName, options, messages) {
347
+ for (const member of options.properties) {
348
+ if (!t.isObjectProperty(member) || member.computed) {
349
+ messages.push(`Prop "${propName}" options cannot contain spreads, methods, or computed keys.`);
350
+ continue;
351
+ }
352
+ const optionName = getObjectKey(member.key);
353
+ if (!optionName) {
354
+ messages.push(`Prop "${propName}" contains an unsupported option key.`);
355
+ continue;
356
+ }
357
+ if (optionName === "type") {
358
+ if (!t.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, Array, or Function.`);
359
+ continue;
360
+ }
361
+ if (optionName === "attr") {
362
+ const value = staticValue(member.value);
363
+ if (value === void 0 && !isExplicitUndefined(member.value)) {
364
+ messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
365
+ continue;
366
+ }
367
+ if (value !== void 0 && value !== false && typeof value !== "string") messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
368
+ continue;
369
+ }
370
+ if (optionName === "reflect") {
371
+ const value = staticValue(member.value);
372
+ if (value === void 0 && !isExplicitUndefined(member.value)) {
373
+ messages.push(`Prop "${propName}" reflect must be a static boolean.`);
374
+ continue;
375
+ }
376
+ if (value !== void 0 && typeof value !== "boolean") messages.push(`Prop "${propName}" reflect must be a static boolean.`);
377
+ continue;
378
+ }
379
+ if (optionName === "values") {
380
+ if (!isStaticStringArray(member.value)) messages.push(`Prop "${propName}" values must be a static string array.`);
381
+ continue;
382
+ }
383
+ if (optionName === "serialize" || optionName === "deserialize") {
384
+ if (!isFunctionLikeReference(member.value)) messages.push(`Prop "${propName}" ${optionName} must be a function.`);
385
+ }
386
+ }
387
+ }
178
388
  function extractRuntimeProp(node) {
179
389
  if (t.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
390
+ if (isPropCall(node)) return extractPropCall(node);
180
391
  if (t.isObjectExpression(node)) {
181
392
  const typeNode = getObjectProperty(node, "type");
182
393
  const attrNode = getObjectProperty(node, "attr");
183
394
  const reflectNode = getObjectProperty(node, "reflect");
184
395
  const defaultNode = getObjectProperty(node, "default");
396
+ const serializeNode = getObjectProperty(node, "serialize");
397
+ const deserializeNode = getObjectProperty(node, "deserialize");
185
398
  const prop = { type: t.isIdentifier(typeNode) ? typeFromConstructorName(typeNode.name) : "unknown" };
186
399
  if (attrNode) {
187
400
  const attr = staticValue(attrNode);
@@ -194,10 +407,68 @@ function extractRuntimeProp(node) {
194
407
  if (defaultNode) {
195
408
  if (!t.isFunctionExpression(defaultNode) && !t.isArrowFunctionExpression(defaultNode)) prop.default = staticValue(defaultNode);
196
409
  }
410
+ if (serializeNode) prop.serialize = true;
411
+ if (deserializeNode) prop.deserialize = true;
412
+ const values = extractStaticStringArray(getObjectProperty(node, "values"));
413
+ if (values) prop.values = values;
197
414
  return prop;
198
415
  }
199
416
  return { type: "unknown" };
200
417
  }
418
+ function isPropCall(node) {
419
+ return t.isCallExpression(node) && t.isIdentifier(node.callee, { name: "prop" });
420
+ }
421
+ function validatePropCall(propName, node, messages) {
422
+ 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.`);
423
+ const optionsNode = node.arguments[1];
424
+ if (optionsNode && !t.isObjectExpression(optionsNode)) {
425
+ messages.push(`Prop "${propName}" prop() options must be an inline object literal.`);
426
+ return;
427
+ }
428
+ if (t.isObjectExpression(optionsNode)) validatePropOptions(propName, optionsNode, messages);
429
+ }
430
+ function extractPropCall(node) {
431
+ var _extractStaticStringA;
432
+ const inputNode = node.arguments[0];
433
+ const optionsNode = node.arguments[1];
434
+ const prop = t.isObjectExpression(optionsNode) ? extractRuntimeProp(optionsNode) : { type: "string" };
435
+ if (isPropConstructorArgument(inputNode)) {
436
+ prop.type = typeFromConstructorName(inputNode.name);
437
+ if (inputNode.name === "Boolean") {
438
+ var _prop$default, _prop$reflect;
439
+ (_prop$default = prop.default) !== null && _prop$default !== void 0 || (prop.default = false);
440
+ (_prop$reflect = prop.reflect) !== null && _prop$reflect !== void 0 || (prop.reflect = true);
441
+ }
442
+ return prop;
443
+ }
444
+ prop.type = "string";
445
+ prop.values = (_extractStaticStringA = extractStaticStringArray(node.arguments[0])) !== null && _extractStaticStringA !== void 0 ? _extractStaticStringA : [];
446
+ return prop;
447
+ }
448
+ function isPropConstructorArgument(node) {
449
+ return t.isIdentifier(node) && isPropConstructorName(node.name);
450
+ }
451
+ function isStaticStringArray(node) {
452
+ return Boolean(extractStaticStringArray(node));
453
+ }
454
+ function extractStaticStringArray(node) {
455
+ if (!t.isArrayExpression(node)) return void 0;
456
+ const values = [];
457
+ for (const item of node.elements) {
458
+ if (!t.isStringLiteral(item)) return void 0;
459
+ values.push(item.value);
460
+ }
461
+ return values;
462
+ }
463
+ function isPropConstructorName(name) {
464
+ return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array" || name === "Function";
465
+ }
466
+ function isExplicitUndefined(node) {
467
+ return t.isIdentifier(node) && node.name === "undefined";
468
+ }
469
+ function isFunctionLikeReference(node) {
470
+ return t.isFunctionExpression(node) || t.isArrowFunctionExpression(node) || t.isIdentifier(node);
471
+ }
201
472
  function typeFromConstructorName(name) {
202
473
  switch (name) {
203
474
  case "String": return "string";
@@ -205,6 +476,7 @@ function typeFromConstructorName(name) {
205
476
  case "Boolean": return "boolean";
206
477
  case "Object": return "object";
207
478
  case "Array": return "array";
479
+ case "Function": return "function";
208
480
  default: return "unknown";
209
481
  }
210
482
  }
@@ -212,23 +484,27 @@ function typeFromConstructorName(name) {
212
484
  //#region packages/web-c/component-analyzer/src/extractSetup.ts
213
485
  function extractSetupMeta(setup) {
214
486
  const events = {};
487
+ const methods = {};
215
488
  const slots = {};
216
489
  const hostAttributes = [];
217
490
  const cssParts = [];
218
491
  if (!setup || t.isSpreadElement(setup) || t.isArgumentPlaceholder(setup)) return {
219
492
  events,
493
+ methods,
220
494
  slots,
221
495
  hostAttributes,
222
496
  cssParts
223
497
  };
224
498
  walk(setup, (node) => {
225
499
  extractEmit(node, events);
500
+ extractExpose(node, methods);
226
501
  extractSlot(node, slots);
227
502
  extractHostAttributes(node, hostAttributes);
228
503
  extractCssParts(node, cssParts);
229
504
  });
230
505
  return {
231
506
  events,
507
+ methods,
232
508
  slots,
233
509
  hostAttributes: uniqueSorted(hostAttributes),
234
510
  cssParts: uniqueSorted(cssParts)
@@ -236,13 +512,21 @@ function extractSetupMeta(setup) {
236
512
  }
237
513
  function extractEmit(node, events) {
238
514
  if (!t.isCallExpression(node)) return;
239
- if (!t.isIdentifier(node.callee, { name: "emit" })) return;
240
- const first = node.arguments[0];
241
- if (!t.isStringLiteral(first)) return;
242
- const eventName = first.value;
243
- events[eventName] || (events[eventName] = {});
244
- const detailNode = node.arguments[1];
245
- if (t.isObjectExpression(detailNode)) events[eventName].detail = inferDetail(detailNode);
515
+ const emitKey = getEmitKey(node.callee);
516
+ if (!emitKey) return;
517
+ events[emitKey] || (events[emitKey] = createComponentEvent(emitKey));
518
+ const detailNode = node.arguments[0];
519
+ if (t.isObjectExpression(detailNode)) events[emitKey].detail = inferDetail(detailNode);
520
+ }
521
+ function getEmitKey(callee) {
522
+ if (t.isMemberExpression(callee)) {
523
+ if (t.isIdentifier(callee.object, { name: "emit" }) && !callee.computed) return getMemberPropertyName(callee.property);
524
+ if (t.isMemberExpression(callee.object) && t.isIdentifier(callee.object.property, { name: "emit" }) && !callee.computed) return getMemberPropertyName(callee.property);
525
+ }
526
+ }
527
+ function getMemberPropertyName(property) {
528
+ if (t.isIdentifier(property)) return property.name;
529
+ if (t.isStringLiteral(property)) return property.value;
246
530
  }
247
531
  function inferDetail(node) {
248
532
  const result = {};
@@ -267,9 +551,111 @@ function extractSlot(node, slots) {
267
551
  var _getJSXStringAttribut;
268
552
  if (!t.isJSXElement(node)) return;
269
553
  const name = node.openingElement.name;
270
- if (!t.isJSXIdentifier(name, { name: "Slot" })) return;
554
+ if (!t.isJSXIdentifier(name, { name: "Slot" }) && !t.isJSXIdentifier(name, { name: "slot" })) return;
271
555
  const slotName = (_getJSXStringAttribut = getJSXStringAttribute(node, "name")) !== null && _getJSXStringAttribut !== void 0 ? _getJSXStringAttribut : "default";
272
- slots[slotName] || (slots[slotName] = {});
556
+ slots[slotName] || (slots[slotName] = { name: slotName });
557
+ }
558
+ function extractExpose(node, methods) {
559
+ if (!t.isCallExpression(node)) return;
560
+ if (!isExposeCallee(node.callee)) return;
561
+ const first = node.arguments[0];
562
+ if (!t.isObjectExpression(first)) return;
563
+ for (const member of first.properties) {
564
+ if (!t.isObjectMethod(member) && !t.isObjectProperty(member)) continue;
565
+ const name = getObjectKey(member.key);
566
+ if (!name) continue;
567
+ methods[name] = extractMethod(member, name);
568
+ }
569
+ }
570
+ function extractMethod(member, name) {
571
+ var _unwrapPromiseType, _formatTsType;
572
+ const fn = t.isObjectMethod(member) ? member : t.isFunctionExpression(member.value) || t.isArrowFunctionExpression(member.value) ? member.value : void 0;
573
+ if (!fn) return { name };
574
+ const returnType = t.isTSTypeAnnotation(fn.returnType) ? fn.returnType.typeAnnotation : void 0;
575
+ const normalizedReturn = fn.async ? (_unwrapPromiseType = unwrapPromiseType(returnType)) !== null && _unwrapPromiseType !== void 0 ? _unwrapPromiseType : returnType : returnType;
576
+ return {
577
+ name,
578
+ parameters: fn.params.map((param, index) => extractMethodParameter(param, index)),
579
+ returns: (_formatTsType = formatTsType(normalizedReturn)) !== null && _formatTsType !== void 0 ? _formatTsType : "unknown",
580
+ async: fn.async
581
+ };
582
+ }
583
+ function extractMethodParameter(param, index) {
584
+ var _formatTsType4;
585
+ if (t.isTSParameterProperty(param)) return extractMethodParameter(param.parameter, index);
586
+ if (t.isAssignmentPattern(param)) {
587
+ var _formatTsType2;
588
+ return {
589
+ name: t.isIdentifier(param.left) ? param.left.name : `arg${index}`,
590
+ type: (_formatTsType2 = formatTsType(getPatternTypeAnnotation(param.left))) !== null && _formatTsType2 !== void 0 ? _formatTsType2 : inferExpressionType(param.right),
591
+ optional: true
592
+ };
593
+ }
594
+ if (t.isRestElement(param)) {
595
+ var _ref, _formatTsType3;
596
+ return {
597
+ name: t.isIdentifier(param.argument) ? param.argument.name : `args${index}`,
598
+ type: (_ref = (_formatTsType3 = formatTsType(getPatternTypeAnnotation(param))) !== null && _formatTsType3 !== void 0 ? _formatTsType3 : formatTsType(getPatternTypeAnnotation(param.argument))) !== null && _ref !== void 0 ? _ref : "unknown[]",
599
+ optional: false,
600
+ rest: true
601
+ };
602
+ }
603
+ return {
604
+ name: t.isIdentifier(param) ? param.name : `arg${index}`,
605
+ type: (_formatTsType4 = formatTsType(getPatternTypeAnnotation(param))) !== null && _formatTsType4 !== void 0 ? _formatTsType4 : "unknown",
606
+ optional: Boolean(t.isIdentifier(param) && param.optional)
607
+ };
608
+ }
609
+ function getPatternTypeAnnotation(node) {
610
+ if (t.isIdentifier(node) || t.isObjectPattern(node) || t.isArrayPattern(node) || t.isRestElement(node)) return t.isTSTypeAnnotation(node.typeAnnotation) ? node.typeAnnotation.typeAnnotation : void 0;
611
+ }
612
+ function unwrapPromiseType(node) {
613
+ if (t.isTSTypeReference(node) && t.isIdentifier(node.typeName, { name: "Promise" })) {
614
+ var _node$typeParameters;
615
+ return (_node$typeParameters = node.typeParameters) === null || _node$typeParameters === void 0 ? void 0 : _node$typeParameters.params[0];
616
+ }
617
+ }
618
+ function formatTsType(node) {
619
+ if (!node) return void 0;
620
+ if (t.isTSStringKeyword(node)) return "string";
621
+ if (t.isTSNumberKeyword(node)) return "number";
622
+ if (t.isTSBooleanKeyword(node)) return "boolean";
623
+ if (t.isTSVoidKeyword(node)) return "void";
624
+ if (t.isTSUnknownKeyword(node)) return "unknown";
625
+ if (t.isTSAnyKeyword(node)) return "any";
626
+ if (t.isTSNullKeyword(node)) return "null";
627
+ if (t.isTSArrayType(node)) {
628
+ var _formatTsType5;
629
+ return `${(_formatTsType5 = formatTsType(node.elementType)) !== null && _formatTsType5 !== void 0 ? _formatTsType5 : "unknown"}[]`;
630
+ }
631
+ if (t.isTSUnionType(node)) return node.types.map((type) => {
632
+ var _formatTsType6;
633
+ return (_formatTsType6 = formatTsType(type)) !== null && _formatTsType6 !== void 0 ? _formatTsType6 : "unknown";
634
+ }).join(" | ");
635
+ if (t.isTSLiteralType(node)) return staticLiteralType(node.literal);
636
+ if (t.isTSTypeReference(node)) {
637
+ var _node$typeParameters2;
638
+ const name = formatEntityName(node.typeName);
639
+ const params = (_node$typeParameters2 = node.typeParameters) === null || _node$typeParameters2 === void 0 ? void 0 : _node$typeParameters2.params;
640
+ return (params === null || params === void 0 ? void 0 : params.length) ? `${name}<${params.map((type) => {
641
+ var _formatTsType7;
642
+ return (_formatTsType7 = formatTsType(type)) !== null && _formatTsType7 !== void 0 ? _formatTsType7 : "unknown";
643
+ }).join(", ")}>` : name;
644
+ }
645
+ return "unknown";
646
+ }
647
+ function formatEntityName(name) {
648
+ return t.isIdentifier(name) ? name.name : `${formatEntityName(name.left)}.${name.right.name}`;
649
+ }
650
+ function staticLiteralType(node) {
651
+ if (t.isStringLiteral(node)) return JSON.stringify(node.value);
652
+ if (t.isNumericLiteral(node)) return String(node.value);
653
+ if (t.isBooleanLiteral(node)) return String(node.value);
654
+ return "unknown";
655
+ }
656
+ function isExposeCallee(callee) {
657
+ if (t.isIdentifier(callee, { name: "expose" })) return true;
658
+ return t.isMemberExpression(callee) && t.isIdentifier(callee.property, { name: "expose" });
273
659
  }
274
660
  function extractHostAttributes(node, hostAttributes) {
275
661
  if (!t.isJSXElement(node)) return;
@@ -381,7 +767,7 @@ function inferType(node) {
381
767
  return { type: "unknown" };
382
768
  }
383
769
  //#endregion
384
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/typeof.js
770
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/typeof.js
385
771
  function _typeof(o) {
386
772
  "@babel/helpers - typeof";
387
773
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -391,7 +777,7 @@ function _typeof(o) {
391
777
  }, _typeof(o);
392
778
  }
393
779
  //#endregion
394
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPrimitive.js
780
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPrimitive.js
395
781
  function toPrimitive(t, r) {
396
782
  if ("object" != _typeof(t) || !t) return t;
397
783
  var e = t[Symbol.toPrimitive];
@@ -403,13 +789,13 @@ function toPrimitive(t, r) {
403
789
  return ("string" === r ? String : Number)(t);
404
790
  }
405
791
  //#endregion
406
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPropertyKey.js
792
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPropertyKey.js
407
793
  function toPropertyKey(t) {
408
794
  var i = toPrimitive(t, "string");
409
795
  return "symbol" == _typeof(i) ? i : i + "";
410
796
  }
411
797
  //#endregion
412
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/defineProperty.js
798
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/defineProperty.js
413
799
  function _defineProperty(e, r, t) {
414
800
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
415
801
  value: t,
@@ -419,7 +805,7 @@ function _defineProperty(e, r, t) {
419
805
  }) : e[r] = t, e;
420
806
  }
421
807
  //#endregion
422
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/objectSpread2.js
808
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/objectSpread2.js
423
809
  function ownKeys(e, r) {
424
810
  var t = Object.keys(e);
425
811
  if (Object.getOwnPropertySymbols) {
@@ -444,28 +830,70 @@ function _objectSpread2(e) {
444
830
  //#endregion
445
831
  //#region packages/web-c/component-analyzer/src/merge.ts
446
832
  function buildComponentRecord(options) {
447
- const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
833
+ const { file, call, runtimeProps, runtimePropsDiagnostics, emits: declaredEvents, typeProps, setupMeta, inlineMeta, shadow, formAssociated } = options;
448
834
  const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
449
- const events = mergeEvents(setupMeta.events, inlineMeta.events);
835
+ const events = mergeEvents(declaredEvents, setupMeta.events, inlineMeta.events);
836
+ const methods = mergeMethods(setupMeta.methods, inlineMeta.methods);
837
+ const models = inlineMeta.models === void 0 ? inferModels(props, events) : normalizeModels(inlineMeta.models);
450
838
  const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
451
839
  const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
452
- const cssVars = unique(toStringArray(inlineMeta.cssVars));
840
+ const cssVars = toCssVarsRecord(inlineMeta.cssVars);
453
841
  const hostAttributes = unique(setupMeta.hostAttributes);
842
+ const restMeta = stripKnownMetaFields(inlineMeta);
454
843
  return {
455
844
  tag: call.tag,
456
845
  name: call.name,
457
846
  exportName: call.exportName,
458
847
  source: file,
459
848
  props,
849
+ runtimeProps,
850
+ runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
460
851
  events,
852
+ methods,
853
+ models,
461
854
  slots,
462
855
  hostAttributes,
463
856
  cssParts,
464
857
  cssVars,
465
858
  description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
466
- meta: stripKnownMetaFields(inlineMeta)
859
+ meta: shadow !== void 0 || formAssociated !== void 0 || restMeta ? _objectSpread2(_objectSpread2({}, restMeta), {}, {
860
+ shadow,
861
+ formAssociated
862
+ }) : void 0
467
863
  };
468
864
  }
865
+ function normalizeModels(value) {
866
+ if (!Array.isArray(value)) return void 0;
867
+ const models = [];
868
+ for (const item of value) {
869
+ if (!item || typeof item !== "object") continue;
870
+ const record = item;
871
+ if (typeof record.prop !== "string" || typeof record.event !== "string") continue;
872
+ models.push({
873
+ prop: record.prop,
874
+ event: record.event,
875
+ eventPath: typeof record.eventPath === "string" ? record.eventPath : void 0
876
+ });
877
+ }
878
+ return models.length ? models : void 0;
879
+ }
880
+ function inferModels(props, events) {
881
+ const models = [];
882
+ for (const prop of Object.keys(props)) {
883
+ var _event$name, _event$key;
884
+ const eventKey = `${prop}Change`;
885
+ const event = events[eventKey];
886
+ if (!(event === null || event === void 0 ? void 0 : event.detail) || !Object.prototype.hasOwnProperty.call(event.detail, prop)) continue;
887
+ 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);
888
+ if (eventName !== `${toKebabCase(prop)}-change`) continue;
889
+ models.push({
890
+ prop,
891
+ event: eventName,
892
+ eventPath: `detail.${prop}`
893
+ });
894
+ }
895
+ return models.length ? models : void 0;
896
+ }
469
897
  function mergeProps(runtimeProps, typeProps, metaProps) {
470
898
  const names = unique([
471
899
  ...Object.keys(runtimeProps),
@@ -474,34 +902,101 @@ function mergeProps(runtimeProps, typeProps, metaProps) {
474
902
  ]);
475
903
  const result = {};
476
904
  for (const name of names) {
477
- var _typeProps$name, _runtimeProps$name, _metaProps$name, _ref, _rp$type, _tp$description, _rp$default, _rp$reflect, _rp$attr;
905
+ var _typeProps$name, _runtimeProps$name, _metaProps$name, _ref, _rp$type, _rp$values, _tp$description, _rp$default, _rp$reflect, _rp$attr, _rp$serialize, _rp$deserialize;
478
906
  const tp = (_typeProps$name = typeProps[name]) !== null && _typeProps$name !== void 0 ? _typeProps$name : {};
479
907
  const rp = (_runtimeProps$name = runtimeProps[name]) !== null && _runtimeProps$name !== void 0 ? _runtimeProps$name : {};
480
908
  const mp = (_metaProps$name = metaProps === null || metaProps === void 0 ? void 0 : metaProps[name]) !== null && _metaProps$name !== void 0 ? _metaProps$name : {};
481
909
  result[name] = {
482
910
  type: (_ref = (_rp$type = rp.type) !== null && _rp$type !== void 0 ? _rp$type : tp.type) !== null && _ref !== void 0 ? _ref : "unknown",
483
911
  required: tp.required,
484
- values: tp.values,
912
+ values: (_rp$values = rp.values) !== null && _rp$values !== void 0 ? _rp$values : tp.values,
485
913
  description: (_tp$description = tp.description) !== null && _tp$description !== void 0 ? _tp$description : mp.description,
486
914
  default: (_rp$default = rp.default) !== null && _rp$default !== void 0 ? _rp$default : mp.default,
487
915
  reflect: (_rp$reflect = rp.reflect) !== null && _rp$reflect !== void 0 ? _rp$reflect : mp.reflect,
488
- attr: (_rp$attr = rp.attr) !== null && _rp$attr !== void 0 ? _rp$attr : mp.attr
916
+ attr: (_rp$attr = rp.attr) !== null && _rp$attr !== void 0 ? _rp$attr : mp.attr,
917
+ serialize: (_rp$serialize = rp.serialize) !== null && _rp$serialize !== void 0 ? _rp$serialize : mp.serialize,
918
+ deserialize: (_rp$deserialize = rp.deserialize) !== null && _rp$deserialize !== void 0 ? _rp$deserialize : mp.deserialize
489
919
  };
490
920
  }
491
921
  return result;
492
922
  }
493
- function mergeEvents(inferred, explicit) {
494
- return _objectSpread2(_objectSpread2({}, inferred), explicit !== null && explicit !== void 0 ? explicit : {});
923
+ function mergeEvents(declared, inferred, explicit) {
924
+ const result = {};
925
+ for (const [key, value] of Object.entries(declared)) result[key] = mergeEvent(value, inferred[key]);
926
+ for (const [key, value] of Object.entries(explicit !== null && explicit !== void 0 ? explicit : {})) if (result[key]) result[key] = normalizeExplicitEvent(key, value, result[key]);
927
+ return result;
928
+ }
929
+ function mergeEvent(primary, fallback) {
930
+ var _primary$key, _primary$name, _primary$reactName, _primary$detail, _primary$bubbles, _primary$composed, _primary$cancelable, _primary$description;
931
+ return {
932
+ key: (_primary$key = primary.key) !== null && _primary$key !== void 0 ? _primary$key : fallback === null || fallback === void 0 ? void 0 : fallback.key,
933
+ name: (_primary$name = primary.name) !== null && _primary$name !== void 0 ? _primary$name : fallback === null || fallback === void 0 ? void 0 : fallback.name,
934
+ reactName: (_primary$reactName = primary.reactName) !== null && _primary$reactName !== void 0 ? _primary$reactName : fallback === null || fallback === void 0 ? void 0 : fallback.reactName,
935
+ detail: (_primary$detail = primary.detail) !== null && _primary$detail !== void 0 ? _primary$detail : fallback === null || fallback === void 0 ? void 0 : fallback.detail,
936
+ bubbles: (_primary$bubbles = primary.bubbles) !== null && _primary$bubbles !== void 0 ? _primary$bubbles : fallback === null || fallback === void 0 ? void 0 : fallback.bubbles,
937
+ composed: (_primary$composed = primary.composed) !== null && _primary$composed !== void 0 ? _primary$composed : fallback === null || fallback === void 0 ? void 0 : fallback.composed,
938
+ cancelable: (_primary$cancelable = primary.cancelable) !== null && _primary$cancelable !== void 0 ? _primary$cancelable : fallback === null || fallback === void 0 ? void 0 : fallback.cancelable,
939
+ description: (_primary$description = primary.description) !== null && _primary$description !== void 0 ? _primary$description : fallback === null || fallback === void 0 ? void 0 : fallback.description
940
+ };
941
+ }
942
+ function normalizeExplicitEvent(key, value, base) {
943
+ var _value$key, _value$name, _value$reactName, _value$detail, _value$bubbles, _value$composed, _value$cancelable, _value$description;
944
+ const fallback = base !== null && base !== void 0 ? base : createComponentEvent(key);
945
+ return {
946
+ key: (_value$key = value.key) !== null && _value$key !== void 0 ? _value$key : fallback.key,
947
+ name: (_value$name = value.name) !== null && _value$name !== void 0 ? _value$name : fallback.name,
948
+ reactName: (_value$reactName = value.reactName) !== null && _value$reactName !== void 0 ? _value$reactName : fallback.reactName,
949
+ detail: (_value$detail = value.detail) !== null && _value$detail !== void 0 ? _value$detail : fallback.detail,
950
+ bubbles: (_value$bubbles = value.bubbles) !== null && _value$bubbles !== void 0 ? _value$bubbles : fallback.bubbles,
951
+ composed: (_value$composed = value.composed) !== null && _value$composed !== void 0 ? _value$composed : fallback.composed,
952
+ cancelable: (_value$cancelable = value.cancelable) !== null && _value$cancelable !== void 0 ? _value$cancelable : fallback.cancelable,
953
+ description: (_value$description = value.description) !== null && _value$description !== void 0 ? _value$description : fallback.description
954
+ };
955
+ }
956
+ function mergeMethods(inferred, explicit) {
957
+ const result = _objectSpread2({}, inferred);
958
+ if (Array.isArray(explicit)) {
959
+ for (const name of explicit) if (typeof name === "string") result[name] = { name };
960
+ }
961
+ return result;
495
962
  }
496
963
  function mergeSlots(inferred, explicit) {
497
- return _objectSpread2(_objectSpread2({}, inferred), explicit !== null && explicit !== void 0 ? explicit : {});
964
+ if (Array.isArray(explicit)) {
965
+ const result = _objectSpread2({}, inferred);
966
+ for (const name of explicit) if (typeof name === "string") result[name] = { name };
967
+ return result;
968
+ }
969
+ if (!explicit || typeof explicit !== "object") return _objectSpread2({}, inferred);
970
+ return _objectSpread2(_objectSpread2({}, inferred), explicit);
498
971
  }
499
972
  function toStringArray(value) {
500
973
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
501
974
  }
975
+ function toCssVarsRecord(value) {
976
+ if (Array.isArray(value)) {
977
+ const result = {};
978
+ for (const item of value) if (typeof item === "string") result[item] = { name: item };
979
+ return result;
980
+ }
981
+ if (value && typeof value === "object") {
982
+ const result = {};
983
+ for (const [name, item] of Object.entries(value)) if (item && typeof item === "object") {
984
+ const description = item.description;
985
+ result[name] = {
986
+ name,
987
+ description: typeof description === "string" ? description : void 0
988
+ };
989
+ } else result[name] = { name };
990
+ return result;
991
+ }
992
+ return {};
993
+ }
502
994
  function unique(values) {
503
995
  return Array.from(new Set(values)).sort();
504
996
  }
997
+ function toKebabCase(value) {
998
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
999
+ }
505
1000
  function stripKnownMetaFields(meta) {
506
1001
  const rest = _objectSpread2({}, meta);
507
1002
  delete rest.description;
@@ -510,6 +1005,10 @@ function stripKnownMetaFields(meta) {
510
1005
  delete rest.slots;
511
1006
  delete rest.cssVars;
512
1007
  delete rest.cssParts;
1008
+ delete rest.shadow;
1009
+ delete rest.formAssociated;
1010
+ delete rest.methods;
1011
+ delete rest.models;
513
1012
  return Object.keys(rest).length ? rest : void 0;
514
1013
  }
515
1014
  //#endregion
@@ -522,24 +1021,37 @@ function analyzeFile(options) {
522
1021
  const ast = parseSource(code, file);
523
1022
  const calls = extractDefineElementCalls(ast);
524
1023
  const localPropTypes = collectLocalPropTypes(ast);
1024
+ const localSetupBindings = collectLocalSetupBindings(ast);
525
1025
  for (const call of calls) {
526
- var _localPropTypes$get;
1026
+ var _localPropTypes$get, _componentOptions$sha, _componentOptions$for;
1027
+ const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
1028
+ for (const message of runtimePropsDiagnostics) diagnostics.push({
1029
+ level: "warning",
1030
+ file,
1031
+ message: `<${call.tag}> ${message}`
1032
+ });
527
1033
  const runtimeProps = extractRuntimeProps(call.options);
1034
+ const emits = extractEmits(call.options);
1035
+ const componentOptions = extractComponentOptions(call.options);
528
1036
  const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
529
1037
  if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
530
1038
  level: "warning",
531
1039
  file,
532
1040
  message: `Cannot resolve local props type "${call.propsTypeName}".`
533
1041
  });
534
- const setupMeta = extractSetupMeta(call.setup);
1042
+ const setupMeta = extractSetupMeta(resolveSetupBinding(call.setup, localSetupBindings));
535
1043
  const inlineMeta = extractInlineMeta(call.options);
536
1044
  components.push(buildComponentRecord({
537
1045
  file,
538
1046
  call,
539
1047
  runtimeProps,
1048
+ runtimePropsDiagnostics,
1049
+ emits,
540
1050
  typeProps,
541
1051
  setupMeta,
542
- inlineMeta
1052
+ inlineMeta,
1053
+ shadow: (_componentOptions$sha = componentOptions.shadow) !== null && _componentOptions$sha !== void 0 ? _componentOptions$sha : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0,
1054
+ formAssociated: (_componentOptions$for = componentOptions.formAssociated) !== null && _componentOptions$for !== void 0 ? _componentOptions$for : typeof inlineMeta.formAssociated === "boolean" ? inlineMeta.formAssociated : void 0
543
1055
  }));
544
1056
  }
545
1057
  } catch (error) {
@@ -555,6 +1067,28 @@ function analyzeFile(options) {
555
1067
  diagnostics
556
1068
  };
557
1069
  }
1070
+ function collectLocalSetupBindings(ast) {
1071
+ const bindings = /* @__PURE__ */ new Map();
1072
+ for (const node of ast.program.body) {
1073
+ if (t.isFunctionDeclaration(node) && node.id) {
1074
+ bindings.set(node.id.name, node);
1075
+ continue;
1076
+ }
1077
+ if (!t.isVariableDeclaration(node)) continue;
1078
+ for (const declarator of node.declarations) {
1079
+ if (!t.isIdentifier(declarator.id) || !declarator.init) continue;
1080
+ if (t.isFunctionExpression(declarator.init) || t.isArrowFunctionExpression(declarator.init)) bindings.set(declarator.id.name, declarator.init);
1081
+ }
1082
+ }
1083
+ return bindings;
1084
+ }
1085
+ function resolveSetupBinding(setup, bindings) {
1086
+ if (t.isIdentifier(setup)) {
1087
+ var _bindings$get;
1088
+ return (_bindings$get = bindings.get(setup.name)) !== null && _bindings$get !== void 0 ? _bindings$get : setup;
1089
+ }
1090
+ return setup;
1091
+ }
558
1092
  function isGlobalUtilityType(name) {
559
1093
  return GLOBAL_UTILITY_TYPES.has(name);
560
1094
  }
@@ -581,7 +1115,7 @@ const GLOBAL_UTILITY_TYPES = new Set([
581
1115
  "Uncapitalize"
582
1116
  ]);
583
1117
  //#endregion
584
- //#region \0@oxc-project+runtime@0.133.0/helpers/esm/asyncToGenerator.js
1118
+ //#region \0@oxc-project+runtime@0.134.0/helpers/esm/asyncToGenerator.js
585
1119
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
586
1120
  try {
587
1121
  var i = n[a](c), u = i.value;