"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { DefinitionKind: () => DefinitionKind, UNKNOWN_TYPE: () => UNKNOWN_TYPE, analyzeSFC: () => analyzeSFC, attachNodeLoc: () => attachNodeLoc, checkForTSProperties: () => checkForTSProperties, genRuntimePropDefinition: () => genRuntimePropDefinition, getTSFile: () => getTSFile, getTSPropertiesKeys: () => getTSPropertiesKeys, handleTSEmitsDefinition: () => handleTSEmitsDefinition, handleTSPropsDefinition: () => handleTSPropsDefinition, inferRuntimeType: () => inferRuntimeType, isSupportedForTSReferencedType: () => isSupportedForTSReferencedType, isTSDeclaration: () => isTSDeclaration, isTSNamespace: () => isTSNamespace, mergeTSProperties: () => mergeTSProperties, namespaceSymbol: () => namespaceSymbol, parseSFC: () => import_common8.parseSFC, resolveDts: () => resolveDts, resolveDtsHMR: () => resolveDtsHMR, resolveMaybeTSUnion: () => resolveMaybeTSUnion, resolveTSIndexedAccessType: () => resolveTSIndexedAccessType, resolveTSLiteralType: () => resolveTSLiteralType, resolveTSNamespace: () => resolveTSNamespace, resolveTSProperties: () => resolveTSProperties, resolveTSReferencedType: () => resolveTSReferencedType, resolveTSScope: () => resolveTSScope, resolveTSTemplateLiteral: () => resolveTSTemplateLiteral, resolveTSTypeOperator: () => resolveTSTypeOperator, resolveTypeElements: () => resolveTypeElements, tsFileCache: () => tsFileCache }); module.exports = __toCommonJS(src_exports); __reExport(src_exports, require("@vue-macros/common"), module.exports); // src/vue/analyze.ts var import_common7 = require("@vue-macros/common"); // src/vue/emits.ts var import_common5 = require("@vue-macros/common"); // src/ts/is.ts var import_types = require("@babel/types"); function isTSDeclaration(node) { return (0, import_types.isDeclaration)(node) && node.type.startsWith("TS"); } // src/ts/resolve-file.ts var import_node_path = __toESM(require("node:path"), 1); // src/ts/scope.ts var import_promises = require("node:fs/promises"); var import_common = require("@vue-macros/common"); var tsFileCache = /* @__PURE__ */ Object.create(null); async function getTSFile(filePath) { if (tsFileCache[filePath]) return tsFileCache[filePath]; const content = await (0, import_promises.readFile)(filePath, "utf-8"); const { code, lang } = (0, import_common.getFileCodeAndLang)(content, filePath); return tsFileCache[filePath] = { kind: "file", filePath, content, ast: import_common.REGEX_SUPPORTED_EXT.test(filePath) ? (0, import_common.babelParse)(code, lang, { cache: true }).body : void 0 }; } function resolveTSScope(scope) { const isFile = scope.kind === "file"; let parentScope; if (!isFile) parentScope = resolveTSScope(scope.scope); const file = isFile ? scope : parentScope.file; const body = isFile ? scope.ast : scope.ast.body; const exports2 = scope.exports; const declarations = isFile ? scope.declarations : { ...resolveTSScope(scope.scope).declarations, ...scope.declarations }; return { isFile, file, body, declarations, exports: exports2 }; } // src/ts/resolve-file.ts var typesResolver; var referencedFiles = /* @__PURE__ */ new Map(); function collectReferencedFile(importer, file) { if (!importer) return; if (!referencedFiles.has(file)) { referencedFiles.set(file, /* @__PURE__ */ new Set([importer])); } else { referencedFiles.get(file).add(importer); } } var resolveCache = /* @__PURE__ */ new Map(); async function resolveDts(id, importer) { const cached = resolveCache.get(importer)?.get(id); if (cached) return cached; if (!typesResolver) { const { ResolverFactory } = await import("oxc-resolver"); typesResolver = new ResolverFactory({ mainFields: ["types"], conditionNames: ["types", "import"], extensions: [".d.ts", ".ts"] }); } const { error, path: resolved } = await typesResolver.async( import_node_path.default.dirname(importer), id ); if (error || !resolved) return; collectReferencedFile(importer, resolved); if (resolveCache.has(importer)) { resolveCache.get(importer).set(id, resolved); } else { resolveCache.set(importer, /* @__PURE__ */ new Map([[id, resolved]])); } return resolved; } var resolveDtsHMR = ({ file, server, modules }) => { const cache = /* @__PURE__ */ new Map(); if (tsFileCache[file]) delete tsFileCache[file]; const affected = getAffectedModules(file); return [...modules, ...affected]; function getAffectedModules(file2) { if (cache.has(file2)) return cache.get(file2); if (!referencedFiles.has(file2)) return /* @__PURE__ */ new Set([]); const modules2 = /* @__PURE__ */ new Set([]); cache.set(file2, modules2); for (const importer of referencedFiles.get(file2)) { const mods = server.moduleGraph.getModulesByFile(importer); if (mods) mods.forEach((m) => modules2.add(m)); getAffectedModules(importer).forEach((m) => modules2.add(m)); } return modules2; } }; // src/ts/resolve-reference.ts var import_types2 = require("@babel/types"); var import_common4 = require("@vue-macros/common"); // src/ts/resolve.ts var import_common3 = require("@vue-macros/common"); // src/ts/property.ts var import_common2 = require("@vue-macros/common"); function mergeTSProperties(a, b) { return { callSignatures: [...a.callSignatures, ...b.callSignatures], constructSignatures: [...a.constructSignatures, ...b.constructSignatures], methods: { ...a.methods, ...b.methods }, properties: { ...a.properties, ...b.properties } }; } function checkForTSProperties(node) { return !!node && [ "TSInterfaceDeclaration", "TSInterfaceBody", "TSTypeLiteral", "TSIntersectionType", "TSMappedType", "TSFunctionType" ].includes(node.type); } async function resolveTSProperties({ type, scope }) { switch (type.type) { case "TSInterfaceBody": return resolveTypeElements(scope, type.body); case "TSTypeLiteral": return resolveTypeElements(scope, type.members); case "TSInterfaceDeclaration": { let properties = resolveTypeElements(scope, type.body.body); if (type.extends) { const resolvedExtends = (await Promise.all( type.extends.map( (node) => node.expression.type === "Identifier" ? resolveTSReferencedType({ scope, type: node.expression }) : void 0 ) )).filter(filterValidExtends); if (resolvedExtends.length > 0) { const ext = (await Promise.all( resolvedExtends.map((resolved) => resolveTSProperties(resolved)) )).reduceRight((acc, curr) => mergeTSProperties(acc, curr)); properties = mergeTSProperties(ext, properties); } } return properties; } case "TSIntersectionType": { let properties = { callSignatures: [], constructSignatures: [], methods: /* @__PURE__ */ Object.create(null), properties: /* @__PURE__ */ Object.create(null) }; for (const subType of type.types) { const resolved = await resolveTSReferencedType({ scope, type: subType }); if (!filterValidExtends(resolved)) continue; properties = mergeTSProperties( properties, await resolveTSProperties(resolved) ); } return properties; } case "TSMappedType": { const properties = { callSignatures: [], constructSignatures: [], methods: /* @__PURE__ */ Object.create(null), properties: /* @__PURE__ */ Object.create(null) }; if (!type.typeParameter.constraint) return properties; const constraint = await resolveTSReferencedType({ type: type.typeParameter.constraint, scope }); if (!constraint || isTSNamespace(constraint)) return properties; const types = resolveMaybeTSUnion(constraint.type); for (const subType of types) { if (subType.type !== "TSLiteralType") continue; const literal = await resolveTSLiteralType({ type: subType, scope: constraint.scope }); if (!literal) continue; const keys = resolveMaybeTSUnion(literal).map( (literal2) => String((0, import_common2.resolveLiteral)(literal2)) ); for (const key of keys) { properties.properties[String(key)] = { value: type.typeAnnotation ? { scope, type: type.typeAnnotation } : null, optional: type.optional === "+" || type.optional === true, signature: { type, scope } }; } } return properties; } case "TSFunctionType": { const properties = { callSignatures: [{ type, scope }], constructSignatures: [], methods: /* @__PURE__ */ Object.create(null), properties: /* @__PURE__ */ Object.create(null) }; return properties; } default: throw new Error(`unknown node: ${type?.type}`); } function filterValidExtends(node) { return !isTSNamespace(node) && checkForTSProperties(node?.type); } } function getTSPropertiesKeys(properties) { return [ .../* @__PURE__ */ new Set([ ...Object.keys(properties.properties), ...Object.keys(properties.methods) ]) ]; } // src/ts/resolve.ts async function resolveTSTemplateLiteral({ type, scope }) { const types = (await resolveKeys("", type.quasis, type.expressions)).map( (k) => (0, import_common3.createStringLiteral)(k) ); return types; async function resolveKeys(prefix, quasis, expressions) { if (expressions.length === 0) { return [prefix + (quasis[0]?.value.cooked ?? "")]; } const [expr, ...restExpr] = expressions; const [quasi, ...restQuasis] = quasis; const subTypes = resolveMaybeTSUnion(expr); const keys = []; for (const type2 of subTypes) { if (!isSupportedForTSReferencedType(type2)) continue; const resolved = await resolveTSReferencedType({ type: type2, scope }); if (!resolved || isTSNamespace(resolved)) continue; const types2 = resolveMaybeTSUnion(resolved.type); for (const type3 of types2) { if (type3.type !== "TSLiteralType") continue; const literal = await resolveTSLiteralType({ type: type3, scope }); if (!literal) continue; const subKeys = resolveMaybeTSUnion(literal).map( (literal2) => String((0, import_common3.resolveLiteral)(literal2)) ); for (const key of subKeys) { const newPrefix = prefix + quasi.value.cooked + String(key); keys.push(...await resolveKeys(newPrefix, restQuasis, restExpr)); } } } return keys; } } async function resolveTSLiteralType({ type, scope }) { if (type.literal.type === "UnaryExpression") return; if (type.literal.type === "TemplateLiteral") { const types = await resolveTSTemplateLiteral({ type: type.literal, scope }); return types; } return type.literal; } function resolveTypeElements(scope, elements) { const properties = { callSignatures: [], constructSignatures: [], methods: /* @__PURE__ */ Object.create(null), properties: /* @__PURE__ */ Object.create(null) }; const tryGetKey = (element) => { try { return (0, import_common3.resolveObjectKey)(element); } catch { } }; for (const element of elements) { switch (element.type) { case "TSCallSignatureDeclaration": properties.callSignatures.push({ scope, type: element }); break; case "TSConstructSignatureDeclaration": properties.constructSignatures.push({ scope, type: element }); break; case "TSMethodSignature": { const key = tryGetKey(element); if (!key) continue; if (properties.properties[key]) continue; if (!properties.methods[key]) properties.methods[key] = []; if (element.typeAnnotation) { properties.methods[key].push({ scope, type: element }); } break; } case "TSPropertySignature": { const key = tryGetKey(element); if (!key) continue; if (!properties.properties[key] && !properties.methods[key]) { const type = element.typeAnnotation?.typeAnnotation; properties.properties[key] = { value: type ? { type, scope } : null, optional: !!element.optional, signature: { type: element, scope } }; } break; } case "TSIndexSignature": break; } } return properties; } async function resolveTSIndexedAccessType({ scope, type }, stacks = []) { const object = await resolveTSReferencedType( { type: type.objectType, scope }, stacks ); if (!object || isTSNamespace(object)) return void 0; const objectType = object.type; if (type.indexType.type === "TSNumberKeyword") { let types; if (objectType.type === "TSArrayType") { types = [objectType.elementType]; } else if (objectType.type === "TSTupleType") { types = objectType.elementTypes.map( (t) => t.type === "TSNamedTupleMember" ? t.elementType : t ); } else if (objectType.type === "TSTypeReference" && objectType.typeName.type === "Identifier" && objectType.typeName.name === "Array" && objectType.typeParameters) { types = objectType.typeParameters.params; } else { return void 0; } return { type: (0, import_common3.createTSUnionType)(types), scope }; } else if (objectType.type !== "TSInterfaceDeclaration" && objectType.type !== "TSTypeLiteral" && objectType.type !== "TSIntersectionType" && objectType.type !== "TSMappedType" && objectType.type !== "TSFunctionType") return void 0; const properties = await resolveTSProperties({ type: objectType, scope: object.scope }); const indexTypes = resolveMaybeTSUnion(type.indexType); const indexes = []; let optional = false; for (const index of indexTypes) { let keys; if (index.type === "TSLiteralType") { const literal = await resolveTSLiteralType({ type: index, scope: object.scope }); if (!literal) continue; keys = resolveMaybeTSUnion(literal).map( (literal2) => String((0, import_common3.resolveLiteral)(literal2)) ); } else if (index.type === "TSTypeOperator") { const keysStrings = await resolveTSTypeOperator({ type: index, scope: object.scope }); if (!keysStrings) continue; keys = resolveMaybeTSUnion(keysStrings).map( (literal) => String((0, import_common3.resolveLiteral)(literal)) ); } else continue; for (const key of keys) { const property = properties.properties[key]; if (property) { optional ||= property.optional; const propertyType = properties.properties[key].value; if (propertyType) indexes.push(propertyType.type); } const methods = properties.methods[key]; if (methods) { optional ||= methods.some((m) => !!m.type.optional); indexes.push( ...methods.map( ({ type: type2 }) => ({ ...type2, type: "TSFunctionType" }) ) ); } } } if (indexes.length === 0) return void 0; if (optional) indexes.push({ type: "TSUndefinedKeyword" }); return { type: (0, import_common3.createTSUnionType)(indexes), scope }; } async function resolveTSTypeOperator({ scope, type }, stacks = []) { if (type.operator !== "keyof") return void 0; const resolved = await resolveTSReferencedType( { type: type.typeAnnotation, scope }, stacks ); if (!resolved || isTSNamespace(resolved)) return void 0; const { type: resolvedType, scope: resolvedScope } = resolved; if (!checkForTSProperties(resolvedType)) return void 0; const properties = await resolveTSProperties({ type: resolvedType, scope: resolvedScope }); return getTSPropertiesKeys(properties).map((k) => (0, import_common3.createStringLiteral)(k)); } function resolveMaybeTSUnion(node) { if (Array.isArray(node)) return node; if (node.type === "TSUnionType") return node.types.flatMap((t) => resolveMaybeTSUnion(t)); return [node]; } // src/ts/resolve-reference.ts function isSupportedForTSReferencedType(node) { return (0, import_types2.isTSType)(node) || node.type === "Identifier" || isTSDeclaration(node); } async function resolveTSReferencedType(ref, stacks = []) { const { scope, type } = ref; if (stacks.some((stack) => stack.scope === scope && stack.type === type)) { return ref; } stacks.push(ref); switch (type.type) { case "TSTypeAliasDeclaration": case "TSParenthesizedType": return resolveTSReferencedType( { scope, type: type.typeAnnotation }, stacks ); case "TSIndexedAccessType": return resolveTSIndexedAccessType({ type, scope }, stacks); case "TSModuleDeclaration": { if (type.body.type === "TSModuleBlock") { const newScope = { kind: "module", ast: type.body, scope }; await resolveTSNamespace(newScope); return newScope.exports; } return void 0; } } if (type.type !== "Identifier" && type.type !== "TSTypeReference") return { scope, type }; await resolveTSNamespace(scope); const refNames = (0, import_common4.resolveIdentifier)( type.type === "TSTypeReference" ? type.typeName : type ); let resolved = resolveTSScope(scope).declarations; for (const name of refNames) { if (isTSNamespace(resolved) && resolved[name]) { resolved = resolved[name]; } else if (type.type === "TSTypeReference") { return { type, scope }; } } return resolved; } // src/ts/namespace.ts var namespaceSymbol = Symbol("namespace"); function isTSNamespace(val) { return !!val && typeof val === "object" && namespaceSymbol in val; } async function resolveTSNamespace(scope) { if (scope.exports) return; const exports2 = { [namespaceSymbol]: true }; scope.exports = exports2; const declarations = { [namespaceSymbol]: true, ...scope.declarations }; scope.declarations = declarations; const { body, file } = resolveTSScope(scope); for (const stmt of body || []) { if (stmt.type === "ExportDefaultDeclaration" && isTSDeclaration(stmt.declaration)) { exports2.default = await resolveTSReferencedType({ scope, type: stmt.declaration }); } else if (stmt.type === "ExportAllDeclaration") { const resolved = await resolveDts(stmt.source.value, file.filePath); if (!resolved) continue; const sourceScope = await getTSFile(resolved); await resolveTSNamespace(sourceScope); Object.assign(exports2, sourceScope.exports); } else if (stmt.type === "ExportNamedDeclaration") { let sourceExports; if (stmt.source) { const resolved = await resolveDts(stmt.source.value, file.filePath); if (!resolved) continue; const scope2 = await getTSFile(resolved); await resolveTSNamespace(scope2); sourceExports = scope2.exports; } else { sourceExports = declarations; } for (const specifier of stmt.specifiers) { let exported; if (specifier.type === "ExportDefaultSpecifier") { exported = sourceExports.default; } else if (specifier.type === "ExportNamespaceSpecifier") { exported = sourceExports; } else if (specifier.type === "ExportSpecifier") { exported = sourceExports[specifier.local.name]; } else { throw new Error(`Unknown export type: ${specifier.type}`); } const name = specifier.exported.type === "Identifier" ? specifier.exported.name : specifier.exported.value; exports2[name] = exported; } if (isTSDeclaration(stmt.declaration)) { const decl = stmt.declaration; if (decl.id?.type === "Identifier") { const exportedName = decl.id.name; declarations[exportedName] = exports2[exportedName] = await resolveTSReferencedType({ scope, type: decl }); } } } else if (isTSDeclaration(stmt)) { if (stmt.id?.type !== "Identifier") continue; declarations[stmt.id.name] = await resolveTSReferencedType({ scope, type: stmt }); } else if (stmt.type === "ImportDeclaration") { const resolved = await resolveDts(stmt.source.value, file.filePath); if (!resolved) continue; const importScope = await getTSFile(resolved); await resolveTSNamespace(importScope); const exports3 = importScope.exports; for (const specifier of stmt.specifiers) { const local = specifier.local.name; let imported; if (specifier.type === "ImportDefaultSpecifier") { imported = exports3.default; } else if (specifier.type === "ImportNamespaceSpecifier") { imported = exports3; } else if (specifier.type === "ImportSpecifier") { const name = specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value; imported = exports3[name]; } else { throw new Error(`Unknown import type: ${specifier.type}`); } declarations[local] = imported; } } } } // src/vue/types.ts var DefinitionKind = /* @__PURE__ */ ((DefinitionKind2) => { DefinitionKind2["Reference"] = "Reference"; DefinitionKind2["Object"] = "Object"; DefinitionKind2["TS"] = "TS"; return DefinitionKind2; })(DefinitionKind || {}); // src/vue/utils.ts var UNKNOWN_TYPE = "Unknown"; async function inferRuntimeType(node) { if (isTSNamespace(node)) return ["Object"]; switch (node.type.type) { case "TSStringKeyword": return ["String"]; case "TSNumberKeyword": return ["Number"]; case "TSBooleanKeyword": return ["Boolean"]; case "TSObjectKeyword": return ["Object"]; case "TSInterfaceDeclaration": case "TSTypeLiteral": { const resolved = await resolveTSProperties({ type: node.type, scope: node.scope }); const types = /* @__PURE__ */ new Set(); if (resolved.callSignatures.length || resolved.constructSignatures.length) { types.add("Function"); } if (Object.keys(resolved.methods).length || Object.keys(resolved.properties).length) { types.add("Object"); } return Array.from(types); } case "TSFunctionType": return ["Function"]; case "TSArrayType": case "TSTupleType": return ["Array"]; case "TSLiteralType": switch (node.type.literal.type) { case "StringLiteral": return ["String"]; case "BooleanLiteral": return ["Boolean"]; case "NumericLiteral": case "BigIntLiteral": return ["Number"]; } break; case "TSTypeReference": if (node.type.typeName.type === "Identifier") { switch (node.type.typeName.name) { case "Array": case "Function": case "Object": case "Set": case "Map": case "WeakSet": case "WeakMap": case "Date": case "Promise": return [node.type.typeName.name]; case "Record": case "Partial": case "Readonly": case "Pick": case "Omit": case "Required": case "InstanceType": return ["Object"]; case "Extract": if (node.type.typeParameters && node.type.typeParameters.params[1]) { const t = await resolveTSReferencedType({ scope: node.scope, type: node.type.typeParameters.params[1] }); if (t) return inferRuntimeType(t); } break; case "Exclude": if (node.type.typeParameters && node.type.typeParameters.params[0]) { const t = await resolveTSReferencedType({ scope: node.scope, type: node.type.typeParameters.params[0] }); if (t) return inferRuntimeType(t); } break; } } break; case "TSUnionType": { const types = (await Promise.all( node.type.types.map(async (subType) => { const resolved = await resolveTSReferencedType({ scope: node.scope, type: subType }); return resolved && !isTSNamespace(resolved) ? inferRuntimeType(resolved) : void 0; }) )).flatMap((t) => t ? t : ["null"]); return [...new Set(types)]; } case "TSIntersectionType": return ["Object"]; case "TSSymbolKeyword": return ["Symbol"]; } return [UNKNOWN_TYPE]; } function attachNodeLoc(node, newNode) { newNode.start = node.start; newNode.end = node.end; } function genRuntimePropDefinition(types, isProduction, properties) { let type; let skipCheck = false; if (types) { const hasBoolean = types.includes("Boolean"); const hasUnknown = types.includes(UNKNOWN_TYPE); if (isProduction || hasUnknown) { types = types.filter( (t) => t === "Boolean" || hasBoolean && t === "String" || t === "Function" ); skipCheck = !isProduction && hasUnknown && types.length > 0; } if (types.length > 0) { type = types.length > 1 ? `[${types.join(", ")}]` : types[0]; } } const pairs = []; if (type) pairs.push(`type: ${type}`); if (skipCheck) pairs.push(`skipCheck: true`); pairs.push(...properties); return pairs.length > 0 ? `{ ${pairs.join(", ")} }` : "null"; } // src/vue/emits.ts async function handleTSEmitsDefinition({ s, file, offset, defineEmitsAst, typeDeclRaw, declId, statement }) { const { definitions, definitionsAst } = await resolveDefinitions({ type: typeDeclRaw, scope: file }); const addEmit = (name, signature) => { const key = (0, import_common5.resolveString)(name); if (definitionsAst.scope === file) { if (definitionsAst.ast.type === "TSIntersectionType") { s.appendLeft(definitionsAst.ast.end + offset, ` & { ${signature} }`); } else { s.appendLeft(definitionsAst.ast.end + offset - 1, ` ${signature} `); } } if (!definitions[key]) definitions[key] = []; const ast = parseSignature(signature); definitions[key].push({ code: signature, ast, scope: void 0 }); }; const setEmit = (name, idx, signature) => { const key = (0, import_common5.resolveString)(name); const def = definitions[key][idx]; if (!def) return false; const ast = parseSignature(signature); attachNodeLoc(def.ast, ast); if (def.scope === file) s.overwriteNode(def.ast, signature, { offset }); definitions[key][idx] = { code: signature, ast, scope: void 0 }; return true; }; const removeEmit = (name, idx) => { const key = (0, import_common5.resolveString)(name); const def = definitions[key][idx]; if (!def) return false; if (def.scope === file) s.removeNode(def.ast, { offset }); definitions[key].splice(idx, 1); return true; }; return { kind: "TS" /* TS */, definitions, definitionsAst, declId, addEmit, setEmit, removeEmit, statementAst: statement, defineEmitsAst }; async function resolveDefinitions(typeDeclRaw2) { const resolved = await resolveTSReferencedType(typeDeclRaw2); if (!resolved || isTSNamespace(resolved)) throw new SyntaxError(`Cannot resolve TS definition.`); const { type: definitionsAst2, scope } = resolved; if (definitionsAst2.type !== "TSInterfaceDeclaration" && definitionsAst2.type !== "TSTypeLiteral" && definitionsAst2.type !== "TSIntersectionType" && definitionsAst2.type !== "TSFunctionType") throw new SyntaxError( `Cannot resolve TS definition: ${definitionsAst2.type}` ); const properties = await resolveTSProperties({ scope, type: definitionsAst2 }); const definitions2 = /* @__PURE__ */ Object.create(null); for (const signature of properties.callSignatures) { const evtArg = signature.type.parameters[0]; if (!evtArg || evtArg.type !== "Identifier" || evtArg.typeAnnotation?.type !== "TSTypeAnnotation") continue; const evtType = await resolveTSReferencedType({ type: evtArg.typeAnnotation.typeAnnotation, scope: signature.scope }); if (isTSNamespace(evtType) || !evtType?.type) continue; const types = evtType.type.type === "TSUnionType" ? evtType.type.types : [evtType.type]; for (const type of types) { if (type.type !== "TSLiteralType") continue; const literal = type.literal; if (!(0, import_common5.isStaticExpression)(literal)) continue; const evt = String( (0, import_common5.resolveLiteral)(literal) ); if (!definitions2[evt]) definitions2[evt] = []; definitions2[evt].push(buildDefinition(signature)); } } for (const evt of Object.keys(properties.properties)) { if (!definitions2[evt]) definitions2[evt] = []; definitions2[evt].push( buildDefinition(properties.properties[evt].signature) ); } return { definitions: definitions2, definitionsAst: buildDefinition({ scope, type: definitionsAst2 }) }; } } function parseSignature(signature) { return (0, import_common5.babelParse)(`interface T {${signature}}`, "ts").body[0].body.body[0]; } function buildDefinition({ type, scope }) { return { code: resolveTSScope(scope).file.content.slice(type.start, type.end), ast: type, scope }; } // src/vue/props.ts var import_common6 = require("@vue-macros/common"); var builtInTypesHandlers = { Partial: { handleType(resolved) { return resolved.typeParameters?.params[0]; }, handleTSProperties(properties) { for (const prop of Object.values(properties.properties)) { prop.optional = true; } return properties; } }, Required: { handleType(resolved) { return resolved.typeParameters?.params[0]; }, handleTSProperties(properties) { for (const prop of Object.values(properties.properties)) { prop.optional = false; } return properties; } }, Readonly: { handleType(resolved) { return resolved.typeParameters?.params[0]; } } // TODO: pick, omit }; async function handleTSPropsDefinition({ s, file, offset, definePropsAst, typeDeclRaw, withDefaultsAst, defaultsDeclRaw, statement, declId }) { const { definitions, definitionsAst } = await resolveDefinitions({ type: typeDeclRaw, scope: file }); const { defaults, defaultsAst } = resolveDefaults(defaultsDeclRaw); const addProp = (name, value, optional) => { const { key, signature, valueAst, signatureAst } = buildNewProp( name, value, optional ); if (definitions[key]) return false; if (definitionsAst.scope === file) { if (definitionsAst.ast.type === "TSIntersectionType") { s.appendLeft(definitionsAst.ast.end + offset, ` & { ${signature} }`); } else { s.appendLeft(definitionsAst.ast.end + offset - 1, ` ${signature} `); } } definitions[key] = { type: "property", value: { code: value, ast: valueAst, scope: void 0 }, optional: !!optional, signature: { code: signature, ast: signatureAst, scope: void 0 }, addByAPI: true }; return true; }; const setProp = (name, value, optional) => { const { key, signature, signatureAst, valueAst } = buildNewProp( name, value, optional ); const def = definitions[key]; if (!definitions[key]) return false; switch (def.type) { case "method": { attachNodeLoc(def.methods[0].ast, signatureAst); if (def.methods[0].scope === file) s.overwriteNode(def.methods[0].ast, signature, { offset }); def.methods.slice(1).forEach((method) => { if (method.scope === file) { s.removeNode(method.ast, { offset }); } }); break; } case "property": { attachNodeLoc(def.signature.ast, signatureAst); if (def.signature.scope === file && !def.addByAPI) { s.overwriteNode(def.signature.ast, signature, { offset }); } break; } } definitions[key] = { type: "property", value: { code: value, ast: valueAst, scope: void 0 }, optional: !!optional, signature: { code: signature, ast: signatureAst, scope: void 0 }, addByAPI: def.type === "property" && def.addByAPI }; return true; }; const removeProp = (name) => { const key = (0, import_common6.resolveString)(name); if (!definitions[key]) return false; const def = definitions[key]; switch (def.type) { case "property": { if (def.signature.scope === file && !def.addByAPI) { s.removeNode(def.signature.ast, { offset }); } break; } case "method": def.methods.forEach((method) => { if (method.scope === file) s.removeNode(method.ast, { offset }); }); break; } delete definitions[key]; return true; }; const getRuntimeDefinitions = async () => { const props = /* @__PURE__ */ Object.create(null); for (const [propName, def] of Object.entries(definitions)) { let prop; if (def.type === "method") { prop = { type: ["Function"], required: !def.optional }; } else { const resolvedType = def.value; if (resolvedType) { const optional = def.optional; prop = { type: await inferRuntimeType({ scope: resolvedType.scope || file, type: resolvedType.ast }), required: !optional }; } else { prop = { type: ["null"], required: false }; } } const defaultValue = defaults?.[propName]; if (defaultValue) { prop.default = (key = "default") => { switch (defaultValue.type) { case "ObjectMethod": return `${defaultValue.kind !== "method" ? `${defaultValue.kind} ` : ""}${defaultValue.async ? `async ` : ""}${key}(${s.sliceNode( defaultValue.params, { offset } )}) ${s.sliceNode(defaultValue.body, { offset })}`; case "ObjectProperty": return `${key}: ${s.sliceNode(defaultValue.value, { offset })}`; } }; } props[propName] = prop; } return props; }; return { kind: "TS" /* TS */, definitions, defaults, declId, addProp, setProp, removeProp, getRuntimeDefinitions, // AST definitionsAst, defaultsAst, statementAst: statement, definePropsAst, withDefaultsAst }; async function resolveUnion(definitionsAst2, scope) { const unionDefs = []; const keys = /* @__PURE__ */ new Set(); for (const type of definitionsAst2.types) { const defs = await resolveDefinitions({ type, scope }).then( ({ definitions: definitions2 }) => definitions2 ); Object.keys(defs).forEach((key) => keys.add(key)); unionDefs.push(defs); } const results = /* @__PURE__ */ Object.create(null); for (const key of keys) { let optional = false; let result; for (const defMap of unionDefs) { const def = defMap[key]; if (!def) { optional = true; continue; } optional ||= def.optional; if (!result) { result = def; continue; } if (result.type === "method" && def.type === "method") { result.methods.push(...def.methods); } else if (result.type === "property" && def.type === "property") { if (!def.value) { continue; } else if (!result.value) { result = def; continue; } if (def.value.ast.type === "TSImportType" || def.value.ast.type === "TSDeclareFunction" || def.value.ast.type === "TSEnumDeclaration" || def.value.ast.type === "TSInterfaceDeclaration" || def.value.ast.type === "TSModuleDeclaration" || result.value.ast.type === "TSImportType" || result.value.ast.type === "TSDeclareFunction" || result.value.ast.type === "TSEnumDeclaration" || result.value.ast.type === "TSInterfaceDeclaration" || result.value.ast.type === "TSModuleDeclaration") { continue; } if (result.value.ast.type === "TSUnionType") { result.value.ast.types.push(def.value.ast); } else { result = { type: "property", value: buildDefinition2({ scope, type: { type: "TSUnionType", types: [result.value.ast, def.value.ast] } }), signature: null, optional, addByAPI: false }; } } else { throw new SyntaxError( `Cannot resolve TS definition. Union type contains different types of results.` ); } } if (result) { results[key] = { ...result, optional }; } } return { definitions: results, definitionsAst: buildDefinition2({ scope, type: definitionsAst2 }) }; } async function resolveIntersection(definitionsAst2, scope) { const results = /* @__PURE__ */ Object.create(null); for (const type of definitionsAst2.types) { const defMap = await resolveDefinitions({ type, scope }).then( ({ definitions: definitions2 }) => definitions2 ); for (const [key, def] of Object.entries(defMap)) { const result = results[key]; if (!result) { results[key] = def; continue; } if (result.type === "method" && def.type === "method") { result.methods.push(...def.methods); } else { results[key] = def; } } } return { definitions: results, definitionsAst: buildDefinition2({ scope, type: definitionsAst2 }) }; } async function resolveNormal(properties) { const definitions2 = /* @__PURE__ */ Object.create(null); for (const [key, sign] of Object.entries(properties.methods)) { const methods = sign.map((sign2) => buildDefinition2(sign2)); definitions2[key] = { type: "method", methods, optional: sign.some((sign2) => !!sign2.type.optional) }; } for (const [key, value] of Object.entries(properties.properties)) { const referenced = value.value ? await resolveTSReferencedType(value.value) : void 0; definitions2[key] = { type: "property", addByAPI: false, value: referenced && !isTSNamespace(referenced) ? buildDefinition2(referenced) : void 0, optional: value.optional, signature: buildDefinition2(value.signature) }; } return definitions2; } async function resolveDefinitions(typeDeclRaw2) { let resolved = await resolveTSReferencedType(typeDeclRaw2) || typeDeclRaw2; let builtInTypesHandler; if (resolved && !isTSNamespace(resolved) && resolved.type.type === "TSTypeReference" && resolved.type.typeName.type === "Identifier") { const typeName = resolved.type.typeName.name; let type; if (typeName in builtInTypesHandlers) { builtInTypesHandler = builtInTypesHandlers[typeName]; type = builtInTypesHandler.handleType(resolved.type); } if (type) resolved = await resolveTSReferencedType({ type, scope: resolved.scope }); } if (!resolved || isTSNamespace(resolved)) { throw new SyntaxError(`Cannot resolve TS definition.`); } const { type: definitionsAst2, scope } = resolved; if (definitionsAst2.type === "TSIntersectionType") { return resolveIntersection(definitionsAst2, scope); } else if (definitionsAst2.type === "TSUnionType") { return resolveUnion(definitionsAst2, scope); } else if (definitionsAst2.type !== "TSInterfaceDeclaration" && definitionsAst2.type !== "TSTypeLiteral" && definitionsAst2.type !== "TSMappedType") { if (definitionsAst2.type === "TSTypeReference") { throw new SyntaxError( `Cannot resolve TS type: ${(0, import_common6.resolveIdentifier)( definitionsAst2.typeName ).join(".")}` ); } else { throw new SyntaxError( `Cannot resolve TS definition: ${definitionsAst2.type}` ); } } let properties = await resolveTSProperties({ scope, type: definitionsAst2 }); if (builtInTypesHandler?.handleTSProperties) properties = builtInTypesHandler.handleTSProperties(properties); return { definitions: await resolveNormal(properties), definitionsAst: buildDefinition2({ scope, type: definitionsAst2 }) }; } function resolveDefaults(defaultsAst2) { if (!defaultsAst2) return {}; const isStatic = defaultsAst2.type === "ObjectExpression" && (0, import_common6.isStaticObjectKey)(defaultsAst2); if (!isStatic) return { defaultsAst: defaultsAst2 }; const defaults2 = (0, import_common6.resolveObjectExpression)(defaultsAst2); if (!defaults2) return { defaultsAst: defaultsAst2 }; return { defaults: defaults2, defaultsAst: defaultsAst2 }; } } function buildNewProp(name, value, optional) { const key = (0, import_common6.resolveString)(name); const signature = `${name}${optional ? "?" : ""}: ${value}`; const valueAst = (0, import_common6.babelParse)(`type T = (${value})`, "ts").body[0].typeAnnotation.typeAnnotation; const signatureAst = (0, import_common6.babelParse)(`interface T {${signature}}`, "ts").body[0].body.body[0]; return { key, signature, signatureAst, valueAst }; } function buildDefinition2({ type, scope }) { return { code: resolveTSScope(scope).file.content.slice(type.start, type.end), ast: type, scope }; } // src/vue/analyze.ts var import_common8 = require("@vue-macros/common"); async function analyzeSFC(s, sfc) { if (!sfc.scriptSetup) throw new Error("Only