UNPKG

@vue-macros/api

Version:

General API for Vue Macros.

329 lines (328 loc) 13.5 kB
import { MagicStringAST, SFC, SFC as SFC$1, TransformError, parseSFC } from "@vue-macros/common"; import * as neverthrow0 from "neverthrow"; import { ResultAsync as ResultAsync$1 } from "neverthrow"; import { BigIntLiteral, BooleanLiteral, CallExpression, Declaration, Expression, ExpressionStatement, Identifier, LVal, Node, NumericLiteral, ObjectMethod, ObjectProperty, Statement, StringLiteral, TSCallSignatureDeclaration, TSConstructSignatureDeclaration, TSFunctionType, TSIndexedAccessType, TSInterfaceBody, TSInterfaceDeclaration, TSIntersectionType, TSLiteralType, TSMappedType, TSMethodSignature, TSModuleBlock, TSParenthesizedType, TSPropertySignature, TSType, TSTypeAliasDeclaration, TSTypeElement, TSTypeLiteral, TSTypeOperator, TSTypeReference, TSUnionType, TemplateLiteral, TypeScript, VariableDeclaration, VoidPattern } from "@babel/types"; import { Plugin } from "vite"; export * from "@vue-macros/common"; //#region src/error.d.ts type ErrorVueSFC = "<script> is not supported, only <script setup>."; type ErrorResolveTS = "Cannot resolve TS definition." | "Cannot resolve TS definition. Union type contains different types of results." | `Cannot resolve TS definition: ${string}` | `Cannot resolve TS type: ${string}`; type ErrorWithDefaults = "withDefaults: first argument must be a defineProps call."; type ErrorUnknownNode = `Unknown node: ${string}` | `Unknown ${"import" | "export"} type: ${string}`; type Error = TransformError<ErrorVueSFC | ErrorResolveTS | ErrorWithDefaults | ErrorUnknownNode>; type ResultAsync<T> = neverthrow0.ResultAsync<T, Error>; //#endregion //#region src/ts/is.d.ts type TSDeclaration = TypeScript & Declaration; declare function isTSDeclaration(node: any): node is TSDeclaration; //#endregion //#region src/ts/scope.d.ts interface TSScopeBase { exports?: TSNamespace; declarations?: TSNamespace; } interface TSFile extends TSScopeBase { kind: "file"; filePath: string; content: string; /** could be undefined if it's a JSON file */ ast: Statement[] | undefined; } interface TSModule extends TSScopeBase { kind: "module"; ast: TSModuleBlock; scope: TSScope; } type TSScope = TSFile | TSModule; declare const tsFileCache: Record<string, TSFile>; declare function getTSFile(filePath: string): Promise<TSFile>; interface ResolvedTSScope { isFile: boolean; file: TSFile; body: Statement[] | undefined; exports?: TSNamespace; declarations?: TSNamespace; } declare function resolveTSScope(scope: TSScope): ResolvedTSScope; //#endregion //#region src/ts/resolve-reference.d.ts interface TSResolvedType<T = Exclude<TSType, TSParenthesizedType> | Exclude<TSDeclaration, TSTypeAliasDeclaration>> { scope: TSScope; type: T; } type TSReferencedType = TSType | Identifier | TSDeclaration; declare function isSupportedForTSReferencedType(node: Node): node is TSReferencedType; /** * Resolve a reference to a type. * * Supports `type` and `interface` only. * * @limitation don't support non-TS declaration (e.g. class, function...) */ declare function resolveTSReferencedType(ref: TSResolvedType<TSReferencedType>, stacks?: TSResolvedType<any>[]): ResultAsync$1<TSResolvedType | TSNamespace | undefined, TransformError<ErrorUnknownNode>>; //#endregion //#region src/ts/namespace.d.ts declare const namespaceSymbol: unique symbol; type TSNamespace = { [K in string]: TSResolvedType | TSNamespace | undefined } & { [namespaceSymbol]: true; }; declare function isTSNamespace(val: unknown): val is TSNamespace; /** * Get exports of the TS file. * * @limitation don't support non-TS declaration (e.g. class, function...) */ declare function resolveTSNamespace(scope: TSScope): ResultAsync$1<void, TransformError<ErrorUnknownNode>>; //#endregion //#region src/ts/property.d.ts interface TSProperties { callSignatures: Array<TSResolvedType<TSCallSignatureDeclaration | TSFunctionType>>; constructSignatures: Array<TSResolvedType<TSConstructSignatureDeclaration>>; methods: Record<string | number, Array<TSResolvedType<TSMethodSignature>>>; properties: Record<string | number, { value: TSResolvedType<TSType> | null; optional: boolean; signature: TSResolvedType<TSPropertySignature | TSMappedType>; }>; } declare function mergeTSProperties(a: TSProperties, b: TSProperties): TSProperties; declare function checkForTSProperties(node?: Node): node is TSInterfaceDeclaration | TSInterfaceBody | TSTypeLiteral | TSIntersectionType | TSMappedType | TSFunctionType; /** * get properties of `interface` or `type` declaration * * @limitation don't support index signature */ declare function resolveTSProperties({ type, scope }: TSResolvedType<TSInterfaceDeclaration | TSInterfaceBody | TSTypeLiteral | TSIntersectionType | TSMappedType | TSFunctionType>): ResultAsync$1<TSProperties, TransformError<ErrorUnknownNode>>; declare function getTSPropertiesKeys(properties: TSProperties): string[]; //#endregion //#region src/ts/resolve-file.d.ts declare function resolveDts(id: string, importer: string): Promise<string | undefined>; declare const resolveDtsHMR: NonNullable<Plugin["handleHotUpdate"]>; //#endregion //#region src/ts/resolve.d.ts declare function resolveTSTemplateLiteral({ type, scope }: TSResolvedType<TemplateLiteral>): ResultAsync$1<StringLiteral[], TransformError<ErrorUnknownNode>>; declare function resolveTSLiteralType({ type, scope }: TSResolvedType<TSLiteralType>): ResultAsync$1<StringLiteral[] | NumericLiteral | StringLiteral | BooleanLiteral | BigIntLiteral | undefined, TransformError<ErrorUnknownNode>>; /** * @limitation don't support index signature */ declare function resolveTypeElements(scope: TSScope, elements: Array<TSTypeElement>): TSProperties; declare function resolveTSIndexedAccessType({ scope, type }: TSResolvedType<TSIndexedAccessType>, stacks?: TSResolvedType<any>[]): ResultAsync$1<{ type: TSUnionType; scope: TSScope; } | void, TransformError<ErrorUnknownNode>>; declare function resolveTSTypeOperator({ scope, type }: TSResolvedType<TSTypeOperator>, stacks?: TSResolvedType<any>[]): ResultAsync$1<StringLiteral[] | void, TransformError<ErrorUnknownNode>>; declare function resolveMaybeTSUnion<T extends Node>(node: T | T[]): T[]; declare function resolveMaybeTSUnion<T extends Node>(node: T): (T | TSType)[]; //#endregion //#region src/vue/types.d.ts declare enum DefinitionKind { /** * Definition is a referenced variable. * * @example defineSomething(foo) */ Reference = "Reference", /** * Definition is a `ObjectExpression`. * * @example defineSomething({ ... }) */ Object = "Object", /** * Definition is TypeScript interface. * * @example defineSomething<{ ... }>() */ TS = "TS", } interface ASTDefinition<T extends Node> { code: string; scope: TSFile | TSModule | undefined; ast: T; } //#endregion //#region src/vue/emits.d.ts declare function handleTSEmitsDefinition({ s, file, offset, defineEmitsAst, typeDeclRaw, declId, statement }: { s: MagicStringAST; file: TSFile; sfc: SFC$1; offset: number; defineEmitsAst: CallExpression; typeDeclRaw: TSType; statement: DefineEmitsStatement; declId?: VoidPattern | LVal; }): ResultAsync$1<TSEmits, TransformError<ErrorResolveTS | ErrorUnknownNode>>; type Emits = TSEmits | undefined; type DefineEmitsStatement = VariableDeclaration | ExpressionStatement; interface EmitsBase { declId?: VoidPattern | LVal; statementAst: DefineEmitsStatement; defineEmitsAst: CallExpression; } interface TSEmits extends EmitsBase { kind: DefinitionKind.TS; definitions: Record<string, ASTDefinition<TSCallSignatureDeclaration | TSFunctionType | TSPropertySignature | TSMappedType>[]>; definitionsAst: ASTDefinition<TSTypeLiteral | TSIntersectionType | TSInterfaceDeclaration | TSFunctionType>; /** * Adds a new emit to the definitions. `definitions` will updated after this call. * * Added definition cannot be set and removed again. * * @example add('change', '(evt: "change", value: string): void') */ addEmit: (name: string | StringLiteral, signature: string) => void; /** * Modify a definition of a emit. `definitions` will updated after this call. * * @limitation Cannot set the emit added by `addEmit`. * * @example setEmit('foo', 0, '(evt: "change", value: string): void') * * @returns false if the definition does not exist. */ setEmit: (name: string | StringLiteral, index: number, signature: string) => boolean; /** * Removes specified emit from TS interface. `definitions` will updated after this call. * * @limitation Cannot remove emit added by `addEmit`. (it will be removed in definitions though) * * @returns `true` if emit was removed, `false` if emit was not found. */ removeEmit: (name: string | StringLiteral, index: number) => boolean; } //#endregion //#region src/vue/props.d.ts declare function handleTSPropsDefinition({ s, file, offset, definePropsAst, typeDeclRaw, withDefaultsAst, defaultsDeclRaw, statement, declId }: { s: MagicStringAST; file: TSFile; sfc: SFC$1; offset: number; definePropsAst: CallExpression; typeDeclRaw: TSType; withDefaultsAst?: CallExpression; defaultsDeclRaw?: DefaultsASTRaw; statement: DefinePropsStatement; declId?: VoidPattern | LVal; }): ResultAsync$1<TSProps, TransformError<ErrorResolveTS | ErrorUnknownNode>>; type Props = TSProps | undefined; type DefinePropsStatement = VariableDeclaration | ExpressionStatement; type DefaultsASTRaw = CallExpression["arguments"][number]; interface PropsBase { declId?: VoidPattern | LVal; statementAst: DefinePropsStatement; definePropsAst: CallExpression; withDefaultsAst?: CallExpression; } interface TSPropsMethod { type: "method"; methods: ASTDefinition<TSMethodSignature>[]; optional: boolean; } interface TSPropsProperty { type: "property"; value: ASTDefinition<TSResolvedType["type"]> | undefined; optional: boolean; signature: ASTDefinition<TSPropertySignature | TSMappedType>; /** Whether added by `addProp` API */ addByAPI: boolean; } interface RuntimePropDefinition { type: string[]; required: boolean; default?: (key?: string) => string; } interface TSProps extends PropsBase { kind: DefinitionKind.TS; definitions: Record<string | number, TSPropsMethod | TSPropsProperty>; definitionsAst: ASTDefinition<TSInterfaceDeclaration | TSTypeLiteral | TSIntersectionType | TSUnionType | TSMappedType | TSTypeReference>; /** * Default value of props. * * `undefined` if not defined or it's not a static expression that cannot be analyzed statically. */ defaults?: Record<string, ObjectMethod | ObjectProperty>; /** * `undefined` if not defined. */ defaultsAst?: Expression; /** * Adds a new prop to the definitions. `definitions` will updated after this call. * * Added definition cannot be set and removed again. * * @example addProp('foo', 'string | boolean') * * @returns false if the definition already exists. */ addProp: (name: string | StringLiteral, type: string, optional?: boolean) => boolean; /** * Modify a definition of a prop. `definitions` will updated after this call. * * @limitation Cannot set the prop added by `addProp`. * * @example setProp('foo', 'string | boolean') * * @returns false if the definition does not exist. */ setProp: (name: string | StringLiteral, type: string, optional?: boolean) => boolean; /** * Removes specified prop from TS interface. `definitions` will updated after this call. * * @limitation Cannot remove prop added by `addProp`. (it will be removed in definitions though) * * @returns `true` if prop was removed, `false` if prop was not found. */ removeProp: (name: string | StringLiteral) => boolean; /** * get runtime definitions. */ getRuntimeDefinitions: () => ResultAsync$1<Record<string, RuntimePropDefinition>, TransformError<ErrorUnknownNode>>; } //#endregion //#region src/vue/analyze.d.ts interface AnalyzeResult { props: Props; emits: Emits; } declare function analyzeSFC(s: MagicStringAST, sfc: SFC$1): ResultAsync$1<AnalyzeResult, Error>; //#endregion //#region src/vue/utils.d.ts declare const UNKNOWN_TYPE = "Unknown"; declare function inferRuntimeType(node: TSResolvedType | TSNamespace): ResultAsync$1<string[], TransformError<ErrorUnknownNode>>; declare function attachNodeLoc(node: Node, newNode: Node): void; declare function genRuntimePropDefinition(types: string[] | undefined, isProduction: boolean, properties: string[]): string; //#endregion export { ASTDefinition, AnalyzeResult, DefaultsASTRaw, DefineEmitsStatement, DefinePropsStatement, DefinitionKind, Emits, EmitsBase, Error, ErrorResolveTS, ErrorUnknownNode, ErrorVueSFC, ErrorWithDefaults, Props, PropsBase, ResultAsync, RuntimePropDefinition, type SFC, TSDeclaration, TSEmits, TSFile, TSModule, TSNamespace, TSProperties, TSProps, TSPropsMethod, TSPropsProperty, TSResolvedType, TSScope, TSScopeBase, UNKNOWN_TYPE, analyzeSFC, attachNodeLoc, checkForTSProperties, genRuntimePropDefinition, getTSFile, getTSPropertiesKeys, handleTSEmitsDefinition, handleTSPropsDefinition, inferRuntimeType, isSupportedForTSReferencedType, isTSDeclaration, isTSNamespace, mergeTSProperties, namespaceSymbol, parseSFC, resolveDts, resolveDtsHMR, resolveMaybeTSUnion, resolveTSIndexedAccessType, resolveTSLiteralType, resolveTSNamespace, resolveTSProperties, resolveTSReferencedType, resolveTSScope, resolveTSTemplateLiteral, resolveTSTypeOperator, resolveTypeElements, tsFileCache };