import { RollupResolve } from "./chunk-E4LU3OPM.mjs"; import { exportsSymbol, getTSFile, isTSDeclaration, isTSExports, mergeTSProperties, resolveTSEntityName, resolveTSExports, resolveTSFileId, resolveTSFileIdNode, resolveTSProperties, resolveTSReferencedType, resolveTSScope, resolveTypeElements, setResolveTSFileIdImpl, tsFileCache, tsFileExportsCache } from "./chunk-5FIR3URH.mjs"; import { keyToString } from "./chunk-VQQLEFAO.mjs"; // src/index.ts import { MagicString } from "@vue-macros/common"; // src/vue/analyze.ts import { DEFINE_EMITS, DEFINE_PROPS, WITH_DEFAULTS, babelParse as babelParse3, isCallOf } from "@vue-macros/common"; // src/vue/props.ts import { babelParse, isStaticObjectKey, resolveObjectExpression } from "@vue-macros/common"; // src/vue/types.ts var DefinitionKind = /* @__PURE__ */ ((DefinitionKind2) => { DefinitionKind2["Reference"] = "Reference"; DefinitionKind2["Object"] = "Object"; DefinitionKind2["TS"] = "TS"; return DefinitionKind2; })(DefinitionKind || {}); // src/vue/utils.ts async function inferRuntimeType(node) { if (isTSExports(node)) return ["Object"]; switch (node.type.type) { case "TSStringKeyword": return ["String"]; case "TSNumberKeyword": return ["Number"]; case "TSBooleanKeyword": return ["Boolean"]; case "TSObjectKeyword": return ["Object"]; case "TSTypeLiteral": { const types = /* @__PURE__ */ new Set(); for (const m of node.type.members) { switch (m.type) { case "TSCallSignatureDeclaration": case "TSConstructSignatureDeclaration": types.add("Function"); break; default: 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"]; default: return [`null`]; } 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); } return ["null"]; 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); } return ["null"]; } } return [`null`]; case "TSUnionType": { const types = (await Promise.all( node.type.types.map(async (subType) => { const resolved = await resolveTSReferencedType({ scope: node.scope, type: subType }); return resolved && !isTSExports(resolved) ? inferRuntimeType(resolved) : void 0; }) )).flatMap((t) => t ? t : ["null"]); return [...new Set(types)]; } case "TSIntersectionType": return ["Object"]; case "TSSymbolKeyword": return ["Symbol"]; case "TSInterfaceDeclaration": return ["Object"]; default: return [`null`]; } } function attachNodeLoc(node, newNode) { newNode.start = node.start; newNode.end = node.end; } function toRuntimeTypeString(types) { return types.length > 1 ? `[${types.join(", ")}]` : types[0]; } // src/vue/props.ts 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 = keyToString(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 = {}; 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) { prop = { type: await inferRuntimeType({ scope: resolvedType.scope || file, type: resolvedType.ast }), required: !def.optional }; } else { prop = { type: ["null"], required: false }; } } const defaultValue = defaults == null ? void 0 : 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 resolveDefinitions(typeDeclRaw2) { const resolved = await resolveTSReferencedType(typeDeclRaw2); if (!resolved || isTSExports(resolved)) throw new SyntaxError(`Cannot resolve TS definition.`); const { type: definitionsAst2, scope } = resolved; if (definitionsAst2.type === "TSIntersectionType") { const results = {}; for (const type of definitionsAst2.types) { const defMap = await resolveDefinitions({ type, scope }).then( ({ definitions: definitions3 }) => definitions3 ); 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: buildDefinition({ scope, type: definitionsAst2 }) }; } else if (definitionsAst2.type === "TSUnionType") { const unionDefs = []; const keys = /* @__PURE__ */ new Set(); for (const type of definitionsAst2.types) { const defs = await resolveDefinitions({ type, scope }).then( ({ definitions: definitions3 }) => definitions3 ); Object.keys(defs).map((key) => keys.add(key)); unionDefs.push(defs); } const results = {}; 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 || (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: buildDefinition({ 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: buildDefinition({ scope, type: definitionsAst2 }) }; } else if (definitionsAst2.type !== "TSInterfaceDeclaration" && definitionsAst2.type !== "TSTypeLiteral" && definitionsAst2.type !== "TSMappedType") throw new SyntaxError( `Cannot resolve TS definition: ${definitionsAst2.type}.` ); const properties = await resolveTSProperties({ scope, type: definitionsAst2 }); const definitions2 = {}; for (const [key, sign] of Object.entries(properties.methods)) { const methods = sign.map((sign2) => buildDefinition(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 && !isTSExports(referenced) ? buildDefinition(referenced) : void 0, optional: value.optional, signature: buildDefinition(value.signature) }; } return { definitions: definitions2, definitionsAst: buildDefinition({ scope, type: definitionsAst2 }) }; } function resolveDefaults(defaultsAst2) { if (!defaultsAst2) return {}; const isStatic = defaultsAst2.type === "ObjectExpression" && isStaticObjectKey(defaultsAst2); if (!isStatic) return { defaultsAst: defaultsAst2 }; const defaults2 = resolveObjectExpression(defaultsAst2); if (!defaults2) return { defaultsAst: defaultsAst2 }; return { defaults: defaults2, defaultsAst: defaultsAst2 }; } function buildNewProp(name, value, optional) { const key = keyToString(name); const signature = `${name}${optional ? "?" : ""}: ${value}`; const valueAst = babelParse(`type T = (${value})`, "ts").body[0].typeAnnotation.typeAnnotation; const signatureAst = babelParse(`interface T {${signature}}`, "ts").body[0].body.body[0]; return { key, signature, signatureAst, valueAst }; } function buildDefinition({ type, scope }) { return { code: resolveTSScope(scope).file.content.slice(type.start, type.end), ast: type, scope }; } } // src/vue/emits.ts import { babelParse as babelParse2, isStaticExpression, resolveLiteral } from "@vue-macros/common"; 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 = keyToString(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 = keyToString(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 = keyToString(name); const def = definitions[key][idx]; if (!def) return false; if (def.scope === file) s.removeNode(def.ast, { offset }); delete definitions[key][idx]; return true; }; return { kind: "TS" /* TS */, definitions, definitionsAst, declId, addEmit, setEmit, removeEmit, statementAst: statement, defineEmitsAst }; function parseSignature(signature) { return babelParse2(`interface T {${signature}}`, "ts").body[0].body.body[0]; } async function resolveDefinitions(typeDeclRaw2) { var _a; const resolved = await resolveTSReferencedType(typeDeclRaw2); if (!resolved || isTSExports(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 = {}; for (const signature of properties.callSignatures) { const evtArg = signature.type.parameters[0]; if (!evtArg || evtArg.type !== "Identifier" || ((_a = evtArg.typeAnnotation) == null ? void 0 : _a.type) !== "TSTypeAnnotation") continue; const evtType = await resolveTSReferencedType({ type: evtArg.typeAnnotation.typeAnnotation, scope: signature.scope }); if (isTSExports(evtType) || !(evtType == null ? void 0 : 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 (!isStaticExpression(literal)) continue; const evt = String( resolveLiteral(literal) ); if (!definitions2[evt]) definitions2[evt] = []; definitions2[evt].push(buildDefinition(signature)); } } return { definitions: definitions2, definitionsAst: buildDefinition({ scope, type: definitionsAst2 }) }; } function buildDefinition({ type, scope }) { return { code: resolveTSScope(scope).file.content.slice(type.start, type.end), ast: type, scope }; } } // src/vue/analyze.ts import { parseSFC } from "@vue-macros/common"; async function analyzeSFC(s, sfc) { if (!sfc.scriptSetup) throw new Error("Only