import ts, { ArrowFunction, Bundle, ClassDeclaration, ClassExpression, CompilerHost, CompilerOptions, ConstructorDeclaration, CustomTransformer, CustomTransformerFactory, Declaration, EntityName, ExportDeclaration, Expression, ExpressionWithTypeArguments, FunctionDeclaration, FunctionExpression, Identifier, ImportDeclaration, JSDocImportTag, MethodDeclaration, ModuleDeclaration, ModuleExportName, Node, NodeArray, NodeFactory, ParseConfigHost, PropertyAccessExpression, QualifiedName, Statement, TransformationContext, TypeAliasDeclaration, TypeChecker, TypeParameterDeclaration, TypeReferenceNode } from 'typescript'; import { NodeConverter, PackExpression } from './reflection-ast.js'; import { SourceFile } from './ts-types.js'; import { ReflectionOp } from '@deepkit/type-spec'; import { Resolver } from './resolver.js'; import { ConfigResolver, MatchResult, ReflectionConfig, ReflectionConfigCache } from './config.js'; export declare function encodeOps(ops: ReflectionOp[]): string; export declare const packSizeByte: number; /** * It can't be more ops than this given number */ export declare const packSize: number; export declare function debugPackStruct(sourceFile: SourceFile, forType: Node, pack: { ops: ReflectionOp[]; stack: PackExpression[]; }): void; interface Frame { variables: { name: string; index: number; }[]; opIndex: number; conditional?: true; previous?: Frame; } type StackEntry = Expression | string | number | boolean; declare class CompilerProgram { forNode: Node; sourceFile?: SourceFile | undefined; protected ops: ReflectionOp[]; protected stack: StackEntry[]; protected mainOffset: number; protected stackPosition: number; protected frame: Frame; protected activeCoRoutines: { ops: ReflectionOp[]; }[]; protected coRoutines: { ops: ReflectionOp[]; }[]; constructor(forNode: Node, sourceFile?: SourceFile | undefined); buildPackStruct(): { ops: ReflectionOp[]; stack: StackEntry[]; }; isEmpty(): boolean; pushConditionalFrame(): void; pushStack(item: StackEntry): number; pushCoRoutine(): void; popCoRoutine(): number; pushOp(...ops: ReflectionOp[]): void; pushOpAtFrame(frame: Frame, ...ops: ReflectionOp[]): void; /** * Returns the index of the `entry` in the stack, if already exists. If not, add it, and return that new index. */ findOrAddStackEntry(entry: any): number; /** * To make room for a stack entry expected on the stack as input for example. */ increaseStackPosition(): number; protected resolveFunctionParameters: Map; resolveFunctionParametersIncrease(fn: Node): void; resolveFunctionParametersDecrease(fn: Node): void; isResolveFunctionParameters(fn: Node): boolean; /** * * Each pushFrame() call needs a popFrame() call. */ pushFrame(implicit?: boolean): Frame; findConditionalFrame(): Frame | undefined; /** * Remove stack without doing it as OP in the processor. Some other command calls popFrame() already, which makes popFrameImplicit() an implicit popFrame. * e.g. union, class, etc. all call popFrame(). the current CompilerProgram needs to be aware of that, which this function is for. */ popFrameImplicit(): void; moveFrame(): void; pushVariable(name: string, frame?: Frame): number; pushTemplateParameter(name: string, withDefault?: boolean): number; findVariable(name: string, frame?: Frame): { frameOffset: number; stackIndex: number; } | undefined; } export declare class Cache { resolver: ReflectionConfigCache; sourceFiles: { [fileName: string]: SourceFile; }; globalSourceFiles?: SourceFile[]; /** * Signals the cache to check if it needs to be cleared. */ tick(): void; } /** * Read the TypeScript AST and generate pack struct (instructions + pre-defined stack). * * This transformer extracts type and add the encoded (so its small and low overhead) at classes and functions as property. * * Deepkit/type can then extract and decode them on-demand. */ export declare class ReflectionTransformer implements CustomTransformer { protected context: TransformationContext; protected cache: Cache; sourceFile: SourceFile; protected f: NodeFactory; protected embedAssignType: boolean; /** * Types added to this map will get a type program directly under it. * This is for types used in the very same file. */ protected compileDeclarations: Map; /** * Types added to this map will get a type program at the top root level of the program. * This is for imported types, which need to be inlined into the current file, as we do not emit type imports (TS will omit them). */ protected embedDeclarations: Map; /** * When a node was embedded or compiled (from the maps above), we store it here to know to not add it again. */ protected compiledDeclarations: Set; protected addImports: { importDeclaration: ImportDeclaration | JSDocImportTag; identifier: Identifier; }[]; protected additionalImports: Map; protected nodeConverter: NodeConverter; protected typeChecker?: TypeChecker; protected resolver: Resolver; protected host: CompilerHost; protected overriddenHost: boolean; protected overriddenConfigResolver?: ConfigResolver; protected compilerOptions: CompilerOptions; /** * When a deep call expression was found a script-wide variable is necessary * as temporary storage. */ protected tempResultIdentifier?: Identifier; protected parseConfigHost: ParseConfigHost; protected intrinsicMetaDeclaration: TypeAliasDeclaration; constructor(context: TransformationContext, cache?: Cache); forHost(host: CompilerHost): this; withReflection(config: ReflectionConfig): this; transformBundle(node: Bundle): Bundle; getTempResultIdentifier(): Identifier; protected getConfigResolver(sourceFile: { fileName: string; }): ConfigResolver; protected getReflectionConfig(sourceFile: { fileName: string; }): MatchResult; protected isWithReflection(sourceFile: SourceFile | undefined, node: Node & { __deepkitConfig?: ReflectionConfig; }): boolean; transformSourceFile(sourceFile: SourceFile): SourceFile; attachAdditionalStatements(statements: NodeArray | Statement[]): Statement[]; protected getModuleType(): 'cjs' | 'esm'; protected getArrowFunctionΩPropertyAccessIdentifier(node: ArrowFunction): Identifier | undefined; protected injectResetΩ(node: T): T; protected createProgramVarFromNode(node: Node, name: EntityName, sourceFile?: SourceFile): Statement[]; protected extractPackStructOfExpression(node: Expression, program: CompilerProgram): void; protected extractPackStructOfType(node: Node | Declaration | ClassDeclaration | ClassExpression, program: CompilerProgram): void; protected knownClasses: { [name: string]: ReflectionOp; }; protected getGlobalLibs(): SourceFile[]; /** * This is a custom resolver based on populated `locals` from the binder. It uses a custom resolution algorithm since * we have no access to the binder/TypeChecker directly and instantiating a TypeChecker per file/transformer is incredible slow. */ protected resolveDeclaration(typeName: EntityName): { declaration: Node; importDeclaration?: ImportDeclaration | JSDocImportTag; typeOnly?: boolean; } | void; protected getDeclarationVariableName(typeName: EntityName): Identifier; /** * The semantic of isExcluded is different from checking if the fileName is part * of reflection config option. isExcluded checks if the file should be excluded * via the exclude option. mainly used to exclude globals and external libraries. */ protected isExcluded(fileName: string): boolean; protected extractPackStructOfTypeReference(type: TypeReferenceNode | ExpressionWithTypeArguments, program: CompilerProgram): void; /** * Returns the class declaration, function/arrow declaration, or block where type was used. */ protected getTypeUser(type: Node): Node; /** * With this function we want to check if `type` is used in the signature itself from the parent of `declaration`. * If so, we do not try to infer the type from runtime values. * * Examples where we do not infer from runtime, `type` being `T` and `declaration` being `` (return false): * * ```typescript * class User { * config: T; * } * * class User { * constructor(public config: T) {} * } * * function do(item: T): void {} * function do(item: T): T {} * ``` * * Examples where we infer from runtime (return true): * * ```typescript * function do(item: T) { * return typeOf; //<-- because of that * } * * function do(item: T) { * class A { * config: T; //<-- because of that * } * return A; * } * * function do(item: T) { * class A { * doIt() { * class B { * config: T; //<-- because of that * } * return B; * } * } * return A; * } * * function do(item: T) { * class A { * doIt(): T { //<-- because of that * } * } * return A; * } * ``` */ protected needsToBeInferred(declaration: TypeParameterDeclaration, type: TypeReferenceNode | ExpressionWithTypeArguments): boolean; protected resolveTypeOnlyImport(entityName: EntityName, program: CompilerProgram): void; protected resolveTypeName(typeName: string, program: CompilerProgram): void; protected resolveTypeParameter(declaration: TypeParameterDeclaration, type: TypeReferenceNode | ExpressionWithTypeArguments, program: CompilerProgram): void; protected createAccessorForEntityName(e: QualifiedName): PropertyAccessExpression; protected findDeclarationInFile(sourceFile: SourceFile | ModuleDeclaration, declarationName: string): Declaration | undefined; protected resolveImportSpecifier(_declarationName: string | ModuleExportName, importOrExport: ExportDeclaration | ImportDeclaration | JSDocImportTag, sourceFile: SourceFile): Declaration | undefined; protected followExport(declarationName: string, statement: ExportDeclaration, sourceFile: SourceFile): Declaration | undefined; protected getTypeOfType(type: Node | Declaration): Expression | undefined; protected packOpsAndStack(program: CompilerProgram): ts.Expression | undefined; /** * Note: We have to duplicate the expressions as it can be that incoming expression are from another file and contain wrong pos/end properties, * so the code generation is then broken when we simply reuse them. Wrong code like ``User.__type = [.toEqual({`` is then generated. * This function is probably not complete, but we add new copies when required. */ protected valueToExpression(value: undefined | PackExpression | PackExpression[]): Expression; /** * A class is decorated with type information by adding a static variable. * * class Model { * static __types = pack(ReflectionOp.string); //<-- encoded type information * title: string; * } */ protected decorateClass(sourceFile: SourceFile, node: ClassDeclaration | ClassExpression): Node; /** * const fn = function() {} * * => const fn = __assignType(function() {}, [34]) */ protected decorateFunctionExpression(expression: FunctionExpression): ts.FunctionExpression | ts.CallExpression; /** * function name() {} * * => function name() {}; name.__type = 34; */ protected decorateFunctionDeclaration(declaration: FunctionDeclaration): ts.ExportAssignment | ts.FunctionDeclaration | ts.Statement[] | undefined; /** * const fn = () => {} * => const fn = __assignType(() => {}, [34]) */ protected decorateArrowFunction(expression: ArrowFunction): ts.ArrowFunction | ts.CallExpression; /** * Object.assign(fn, {__type: []}) is much slower than a custom implementation like * * assignType(fn, []) * * where we embed assignType() at the beginning of the type. */ protected wrapWithAssignType(fn: Expression, type: Expression): ts.CallExpression; /** * Checks if reflection was disabled/enabled in file via JSDoc attribute for a particular * Node, e.g `@reflection no`. If nothing is found, "reflection" config option needs to be used. */ protected getExplicitReflectionMode(sourceFile: SourceFile | undefined, node: Node): boolean | undefined; } export declare class DeclarationTransformer extends ReflectionTransformer { protected addExports: { identifier: string; }[]; transformSourceFile(sourceFile: SourceFile): SourceFile; } export declare const transformer: CustomTransformerFactory; export declare const declarationTransformer: CustomTransformerFactory; export {};