@trapi/metadata
Version:
Generate REST-API metadata scheme from TypeScript Decorators.
741 lines (740 loc) • 32.6 kB
text/typescript
import { BaseError } from "@ebec/core";
import { ClassDeclaration, CompilerOptions, EnumDeclaration, EnumMember, Expression, HasInitializer, InterfaceDeclaration, JSDoc, JSDocComment, JSDocTag, LiteralTypeNode, MethodDeclaration, Node, NodeArray, ParameterDeclaration, PropertyDeclaration, PropertySignature, SyntaxKind, Token, TypeAliasDeclaration, TypeChecker, TypeNode, TypeReferenceNode } from "typescript";
import { BaseType, Controller, DecoratorArgument, DecoratorHost, DecoratorSource, DecoratorTarget, DependencyResolver, Extension, HandlerContext, IControllerGenerator, IParameterGenerator, IResolverCache, JsDocHandlerContext, JsDocMatch, JsDocSource, Match, Metadata, Method, NeverType, Parameter, Preset, PrimitiveType, RefEnumType, RefObjectType, ReferenceType, Registry, ResolverProperty, Type, UnmatchedDecoratorReport, Validator, VoidType } from "@trapi/core";
//#region src/adapters/cache/types.d.ts
interface CacheOptions {
/**
* Specify if the cache driver should be enabled.
*
* Default: false
* */
enabled: boolean;
/**
* Directory relative or absolute path. Auto-created on first save.
*
* Default: tmpDir()
*/
directoryPath: string;
/**
* Specify the cache file name. When set, the cache becomes a single-slot
* store at this exact name (instead of one file per cache key). The
* in-file `cacheKey` check still rejects mismatches; you just lose
* multi-key caching.
*
* Default: .trapi-metadata-{cacheKey}.json
*/
fileName?: string;
/**
* Files older than this many milliseconds are pruned opportunistically
* after each successful save. Set to `0` to disable eviction.
*
* Default: 7 days
*/
maxAgeMs: number;
}
type CacheOptionsInput = Partial<CacheOptions>;
type CacheData = {
/**
* Opaque composite key — sha256 over (schema version, source files content,
* compiler options, resolved registry shape, preset name). The reader
* cross-checks this against the expected key to defend against collisions
* or schema drift.
*/
cacheKey: string; /** Stamped at write time; rejected on read if not equal to the current value. */
schemaVersion: string;
} & Metadata;
interface ICacheClient {
save(data: CacheData): Promise<string | undefined>;
get(cacheKey: string): Promise<CacheData | undefined>;
/** Prune cache files older than `maxAgeMs`. Safe to call concurrently. */
evict(): Promise<void>;
}
//#endregion
//#region src/adapters/cache/client.d.ts
declare class CacheClient implements ICacheClient {
private readonly options;
constructor(input?: string | boolean | CacheOptionsInput);
save(data: CacheData): Promise<string | undefined>;
get(cacheKey: string): Promise<CacheData | undefined>;
/**
* Prune cache files older than `maxAgeMs`. No-op when disabled or when
* `maxAgeMs <= 0`. Each unlink is best-effort — a concurrent generator
* may have already removed the file.
*/
evict(): Promise<void>;
private resolveFilePath;
private ensureDirectory;
}
//#endregion
//#region src/adapters/cache/constants.d.ts
/**
* Bump whenever the on-disk cache shape changes incompatibly
* (Metadata, Controller, Method, Parameter, resolver type nodes,
* or the cache wrapper itself). Old cache files with a different
* version are rejected on read.
*/
declare const CACHE_SCHEMA_VERSION = "3";
declare const CACHE_FILE_PREFIX = ".trapi-metadata-";
declare const CACHE_FILE_SUFFIX = ".json";
/** 7 days. */
declare const CACHE_DEFAULT_MAX_AGE_MS: number;
//#endregion
//#region src/adapters/cache/utils.d.ts
declare function buildCacheOptions(input?: string | boolean | CacheOptionsInput): CacheOptions;
type CacheKeyParts = {
schemaVersion: string;
sourceFilesHash: string;
compilerOptionsHash: string;
registryHash: string;
presetName?: string;
};
/**
* Combines all key contributors into a single sha256 hex string. The order is
* stable; each part is null-separated to avoid concatenation ambiguity.
*/
declare function composeCacheKey(parts: CacheKeyParts): string;
/**
* Hash a stable JSON projection of `compilerOptions`. Sorting keys keeps the
* output deterministic regardless of declaration order in tsconfig.json.
*/
declare function hashCompilerOptions(options?: CompilerOptions): string;
/**
* Hash the resolved registry's structural shape. Catches structural changes
* (handler added/removed/renamed, marker changed, replaces policy changed)
* AND most logic changes via `apply.toString()`. Misses changes that are
* purely captured-variable shifts in factory-built handlers — acceptable
* trade-off for catching local preset edits.
*/
declare function hashRegistry(registry: Registry): string;
//#endregion
//#region src/adapters/filesystem/tsconfig/types.d.ts
type TsconfigLoadContext = {
cwd?: string;
name?: string;
};
type TsCompilerOptions = CompilerOptions;
type TsConfig = {
compilerOptions?: TsCompilerOptions;
[key: string]: any;
};
//#endregion
//#region src/adapters/filesystem/tsconfig/module.d.ts
declare function loadTSConfig(context?: TsconfigLoadContext): Promise<TsConfig>;
declare function softLoadTsconfig(context?: TsconfigLoadContext): Promise<TsConfig>;
//#endregion
//#region src/core/config/types.d.ts
type EntryPointOptions = {
cwd: string;
pattern: string;
};
type EntryPoint = string | string[] | EntryPointOptions | EntryPointOptions[];
type MetadataGeneratorOptions = {
/**
* The entry point to your API.
*/
entryPoint: EntryPoint;
/**
* Directory to ignore during TypeScript files scan.
* Default: []
*/
ignore?: string[];
/**
* Directory to allow during TypeScript files scan.
* Default: []
*/
allow?: string[];
/**
* Directory to store and cache metadata cache files.
* Default: false
*/
cache?: string | boolean | Partial<CacheOptions>;
/**
* Decorator preset to load. Either:
* - a string identifier resolved via {@link resolvePresetByName}
* (npm package, relative path, or `module:` specifier), or
* - an inline {@link Preset} object (still walked through `loadRegistry`,
* so its `extends` chain — if any — is resolved by name).
*
* If both `preset` and `registry` are provided, the resolved preset
* registry comes first and the inline `registry` is appended after.
* Inline handlers therefore run last (winning on scalar mutations like
* `into('path')`) and additively contribute on `append`-style fields.
*/
preset?: string | Preset;
/**
* An already-resolved decorator {@link Registry}. Use this to wire
* decorator handlers manually without authoring a full {@link Preset}.
*
* If provided alongside `preset`, the registry is appended to the
* preset-derived registry (preset first, registry second). Inline
* handlers cannot carry `replaces` semantics — those are enforced at
* preset-load time. To remove a preset handler, author a `Preset` with
* `replaces` and pass it via `preset` instead.
*/
registry?: Registry;
/**
* Controls how unmatched decorators (decorators with no matching handler
* in the resolved registry) are surfaced.
*
* - `false` / unset (default): silent.
* - `true`: emit a single `console.warn` listing every unmatched decorator
* at the end of generation. Useful for catching typos (e.g. `@Hiden`
* instead of `@Hidden`) and unwired decorators in custom presets.
* - `'throw'`: throw a `GeneratorError` instead of warning. Useful as a
* CI gate.
*
* If `onUnmatchedDecorator` is also set, the callback is invoked instead
* of warning/throwing — collection still happens, but reporting is yours.
*
* Note: JSDoc tags are not currently included in strict-mode reporting
* because standard documentation tags (`@param`, `@returns`, ...) would
* generate excessive noise.
*/
strict?: boolean | 'throw';
/**
* Optional callback invoked at the end of generation with all unmatched-
* decorator reports collected during the run. Replaces the default
* `console.warn` / `throw` behaviour of `strict` — when set, the callback
* is the terminal step (no warn, no throw).
*
* Setting this implicitly enables collection — you don't also need to set
* `strict`.
*/
onUnmatchedDecorator?: (reports: UnmatchedDecoratorReport[]) => void;
};
type MetadataGenerateOptions = MetadataGeneratorOptions & {
/**
* Path to tsconfig.json or a TsConfig object.
*/
tsconfig?: string | TsConfig;
};
//#endregion
//#region src/core/metadata/types.d.ts
type MetadataGeneratorContext = {
options: MetadataGeneratorOptions;
sourceFiles: string[];
compilerOptions?: CompilerOptions;
};
interface IMetadataGenerator {
generate(): Promise<Metadata>;
}
/**
* Narrow context interface for the type resolver.
* Contains only what TypeNodeResolver needs — no generator methods.
*/
interface IResolverContext {
readonly typeChecker: TypeChecker;
readonly nodes: Node[];
readonly registry: Registry;
readonly resolverCache: IResolverCache;
isExportedNode(node: Node): boolean;
}
/**
* Callback interface for resolver → generator communication.
* Allows the resolver to register discovered reference types
* without importing the MetadataGenerator class.
*/
interface IReferenceTypeRegistry {
addReferenceType(type: ReferenceType): void;
getReferenceType(refName: string): ReferenceType | undefined;
registerDependencyResolver(callback: DependencyResolver): void;
}
/**
* Context interface for generators.
* Extends IResolverContext and IReferenceTypeRegistry so generators
* can pass `this.current` directly to TypeNodeResolver.
*/
interface IGeneratorContext extends IResolverContext, IReferenceTypeRegistry {
readonly config: MetadataGeneratorOptions;
readonly registry: Registry;
/**
* Optional sink for unmatched-decorator reports. Generators forward to
* this when `config.strict` is enabled. The metadata generator drains the
* sink after the controller walk and emits a single warning summary.
*/
reportUnmatchedDecorator?(report: UnmatchedDecoratorReport): void;
}
//#endregion
//#region src/core/error/base.d.ts
declare class MetadataError extends BaseError {}
//#endregion
//#region src/core/error/config.d.ts
declare class ConfigError extends MetadataError {}
//#endregion
//#region src/core/error/config-codes.d.ts
declare const ConfigErrorCode: {
readonly TSCONFIG_MALFORMED: "CONFIG_TSCONFIG_MALFORMED";
readonly PRESET_NOT_FOUND: "CONFIG_PRESET_NOT_FOUND";
readonly PRESET_MISSING: "CONFIG_PRESET_MISSING";
};
type ConfigErrorCode = typeof ConfigErrorCode[keyof typeof ConfigErrorCode];
//#endregion
//#region src/core/error/generator.d.ts
declare class GeneratorError extends MetadataError {}
declare function isGeneratorError(input: unknown): input is GeneratorError & {
code: string;
};
//#endregion
//#region src/core/error/generator-codes.d.ts
declare const GeneratorErrorCode: {
readonly CONTROLLER_NO_SOURCE_FILE: "GENERATOR_CONTROLLER_NO_SOURCE_FILE";
readonly CONTROLLER_NO_NAME: "GENERATOR_CONTROLLER_NO_NAME";
readonly PARAMETER_GENERATION_FAILED: "GENERATOR_PARAMETER_GENERATION_FAILED";
readonly BODY_PARAMETER_DUPLICATE: "GENERATOR_BODY_PARAMETER_DUPLICATE";
readonly BODY_FORM_CONFLICT: "GENERATOR_BODY_FORM_CONFLICT";
readonly STRICT_UNMATCHED_DECORATORS: "GENERATOR_STRICT_UNMATCHED_DECORATORS";
};
type GeneratorErrorCode = typeof GeneratorErrorCode[keyof typeof GeneratorErrorCode];
//#endregion
//#region src/core/error/parameter.d.ts
type UnsupportedTypeContext = {
decoratorName: string;
propertyName: string;
type: BaseType;
node?: Node;
};
type UnsupportedMethodContext = {
decoratorName: string;
propertyName: string;
method: string;
node?: Node;
};
type PathMatchInvalidContext = {
decoratorName: string;
propertyName: string;
path: string;
node?: Node;
};
type ScopeRequiredContext = {
decoratorName: string;
node?: Node;
};
declare class ParameterError extends MetadataError {
static typeUnsupported(context: UnsupportedTypeContext): ParameterError;
static methodUnsupported(context: UnsupportedMethodContext): ParameterError;
static invalidPathMatch(context: PathMatchInvalidContext): ParameterError;
static scopeRequired(context: ScopeRequiredContext): ParameterError;
static invalidExampleSchema(): ParameterError;
static getCurrentLocation(node: Node): string;
}
//#endregion
//#region src/core/error/parameter-codes.d.ts
declare const ParameterErrorCode: {
readonly TYPE_UNSUPPORTED: "PARAMETER_TYPE_UNSUPPORTED";
readonly METHOD_UNSUPPORTED: "PARAMETER_METHOD_UNSUPPORTED";
readonly PATH_MISMATCH: "PARAMETER_PATH_MISMATCH";
readonly SCOPE_REQUIRED: "PARAMETER_SCOPE_REQUIRED";
readonly INVALID_EXAMPLE: "PARAMETER_INVALID_EXAMPLE";
};
type ParameterErrorCode = typeof ParameterErrorCode[keyof typeof ParameterErrorCode];
//#endregion
//#region src/core/error/resolver.d.ts
declare class ResolverError extends MetadataError {
readonly file?: string;
readonly line?: number;
constructor(message: string, node?: Node | TypeNode, options?: boolean | {
onlyCurrent?: boolean;
cause?: unknown;
});
}
declare function isResolverError(input: unknown): input is ResolverError;
declare function prettyLocationOfNode(node: Node | TypeNode): {
text: string;
file: string;
line?: number;
} | undefined;
declare function prettyTroubleCause(node: Node | TypeNode, onlyCurrent?: boolean): string;
//#endregion
//#region src/core/error/validator.d.ts
declare class ValidatorError extends MetadataError {}
//#endregion
//#region src/core/error/validator-codes.d.ts
declare const ValidatorErrorCode: {
readonly EXPECTED_NUMBER: "VALIDATOR_EXPECTED_NUMBER";
readonly EXPECTED_DATE: "VALIDATOR_EXPECTED_DATE";
readonly EXPECTED_STRING: "VALIDATOR_EXPECTED_STRING";
};
type ValidatorErrorCode = typeof ValidatorErrorCode[keyof typeof ValidatorErrorCode];
//#endregion
//#region src/adapters/typescript/resolver/types.d.ts
type OverrideToken = Token<SyntaxKind.QuestionToken> | Token<SyntaxKind.PlusToken> | Token<SyntaxKind.MinusToken>;
type UsableDeclaration = InterfaceDeclaration | ClassDeclaration | PropertySignature | TypeAliasDeclaration | EnumMember;
type TypeNodeResolverContext = {
[name: string]: TypeReferenceNode | TypeNode;
};
type SubResolverContext = {
readonly typeChecker: TypeChecker;
readonly current: IResolverContext & IReferenceTypeRegistry;
readonly parentNode?: Node;
readonly context: TypeNodeResolverContext;
readonly referencer?: TypeNode;
resolveType(typeNode: TypeNode, parentNode?: Node, context?: TypeNodeResolverContext, referencer?: TypeNode): Type;
propertyFromSignature(sig: PropertySignature, overrideToken?: OverrideToken): ResolverProperty;
propertyFromDeclaration(decl: PropertyDeclaration | ParameterDeclaration, overrideToken?: OverrideToken): ResolverProperty;
getNodeDescription(node: UsableDeclaration | PropertyDeclaration | ParameterDeclaration | EnumDeclaration): string | undefined;
getNodeExample(node: UsableDeclaration | PropertyDeclaration | ParameterDeclaration | EnumDeclaration): unknown;
getNodeExtensions(node: UsableDeclaration | PropertyDeclaration | ParameterDeclaration | EnumDeclaration): Extension[];
};
//#endregion
//#region src/adapters/typescript/resolver/sub/array.d.ts
declare function resolveArrayType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/base.d.ts
declare class ResolverBase {
protected hasPublicModifier(node: Node): boolean;
protected hasStaticModifier(node: Node): boolean | undefined;
protected isAccessibleParameter(node: Node): boolean;
}
//#endregion
//#region src/adapters/typescript/resolver/sub/indexed-access.d.ts
declare function resolveIndexedAccessType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/intersection.d.ts
declare function resolveIntersectionType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/literal.d.ts
declare function resolveLiteralType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
declare function getLiteralValue(typeNode: LiteralTypeNode): string | number | boolean | null;
//#endregion
//#region src/adapters/typescript/resolver/sub/mapped.d.ts
declare function resolveMappedType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/object-literal.d.ts
declare function resolveObjectLiteralType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/primitive.d.ts
declare class PrimitiveResolver {
protected registry: Registry;
constructor(registry: Registry);
resolve(node: TypeNode, parentNode?: Node): PrimitiveType | NeverType | VoidType | undefined;
resolveSyntaxKind(syntaxKind: SyntaxKind): "string" | "boolean" | "void" | "undefined" | "null" | "number" | "bigint" | "never" | undefined;
}
//#endregion
//#region src/adapters/typescript/resolver/sub/reference.d.ts
declare class ReferenceResolver extends ResolverBase {
protected typeChecker: TypeChecker;
constructor(typeChecker: TypeChecker);
merge(referenceTypes: ReferenceType[]): ReferenceType;
mergeManyRefEnums(many: RefEnumType[]): RefEnumType;
mergeRefEnums(first: RefEnumType, second: RefEnumType): RefEnumType;
mergeManyRefObjects(many: RefObjectType[]): RefObjectType;
mergeRefObject(first: RefObjectType, second: RefObjectType): RefObjectType;
transformEnum(declaration: EnumDeclaration, enumName: string): RefEnumType;
transformEnumMember(declaration: EnumMember, enumName: string): RefEnumType;
}
//#endregion
//#region src/adapters/typescript/resolver/sub/tuple.d.ts
declare function resolveTupleType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/type-operator.d.ts
declare function resolveTypeOperatorType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/sub/union.d.ts
declare function resolveUnionType(typeNode: TypeNode, ctx: SubResolverContext): Type | undefined;
//#endregion
//#region src/adapters/typescript/resolver/module.d.ts
declare class TypeNodeResolver extends ResolverBase {
private static readonly MAX_DEPTH;
private readonly typeNode;
private readonly current;
private readonly parentNode?;
private context;
private readonly referencer;
private readonly depth;
private readonly primitiveResolver;
private readonly referenceResolver;
constructor(typeNode: TypeNode, current: IResolverContext & IReferenceTypeRegistry, parentNode?: Node, context?: TypeNodeResolverContext, referencer?: TypeNode, depth?: number);
/**
* @deprecated Use resolverCache.clear() on the context instead.
* Kept for backward compatibility — no-ops since cache is now instance-scoped.
*/
static clearCache(): void;
resolve(): Type;
private createSubResolverContext;
private resolveNestedType;
private throwUnknownType;
private resolveConditionalType;
private resolveTypeReference;
private static readonly CHECKER_RESOLVABLE_UTILITY_TYPES;
private static isCheckerResolvableUtilityType;
private resolveUtilityTypeViaChecker;
/**
* Shared checker delegation: resolves a type node by letting the TS
* type checker evaluate it, converting back to a TypeNode, and
* recursively resolving the result.
*/
private resolveTypeViaChecker;
/**
* Check if a type reference has type arguments that reference unbound
* type parameters from this.context (e.g. `Awaited<T>` where T is a
* generic parameter mapped in context).
*/
private hasUnboundContextArgs;
private static resolveSpecialReference;
private getDateType;
private static getDesignatedModels;
private getReferenceType;
private getTypeAliasReference;
private getModelReference;
private static getRefTypeName;
private contextualizedName;
private createCircularDependencyResolver;
private static nodeIsUsable;
private getModelTypeDeclarations;
private getModelTypeDeclaration;
private hasFlag;
private getSymbolAtLocation;
private getModelProperties;
private propertyFromSignature;
private propertyFromDeclaration;
private getModelAdditionalProperties;
private typeArgumentsToContext;
private getModelInheritedProperties;
private getNodeDescription;
private static getNodeFormat;
private getNodeExample;
protected getNodeExtensions(node: UsableDeclaration | PropertyDeclaration | ParameterDeclaration | EnumDeclaration): Extension[];
}
//#endregion
//#region src/adapters/typescript/resolver/cache.d.ts
declare class ResolverCache implements IResolverCache {
private referenceTypes;
private inProgressTypes;
getCachedType(name: string): ReferenceType | undefined;
setCachedType(name: string, type: ReferenceType): void;
isInProgress(name: string): boolean;
markInProgress(name: string): void;
clearInProgress(name: string): void;
clear(): void;
}
//#endregion
//#region src/adapters/typescript/resolver/utils.d.ts
declare function getNodeDescription(node: Node, typeChecker: TypeChecker): string | undefined;
declare function toTypeNodeOrFail(typeChecker: TypeChecker, ...args: Parameters<TypeChecker['typeToTypeNode']>): TypeNode;
//#endregion
//#region src/adapters/typescript/resolver/extension/module.d.ts
declare function getNodeExtensions(node: Node, registry: Registry): Extension[];
//#endregion
//#region src/adapters/typescript/node-utils/types.d.ts
interface NodeDecorator {
text: string;
arguments: any[];
typeArguments: any[];
}
//#endregion
//#region src/adapters/typescript/node-utils/module.d.ts
/**
* Get Decorators for a specific node.
*
* @param node
* @param isMatching
*/
declare function getNodeDecorators(node: Node, isMatching?: (data: NodeDecorator) => boolean): NodeDecorator[];
//#endregion
//#region src/adapters/typescript/initializer.d.ts
declare function getInitializerValue(initializer?: Expression, typeChecker?: TypeChecker, type?: Type): unknown;
declare const hasInitializer: (node: Node) => node is HasInitializer;
//#endregion
//#region src/adapters/typescript/js-doc/constants.d.ts
declare enum JSDocTagName {
ABSTRACT = "abstract",
ACCESS = "access",
ALIAS = "alias",
ASYNC = "async",
/**
* Alias for @extends
*/
AUGMENTS = "augments",
AUTHOR = "author",
DEFAULT = "default",
DEPRECATED = "deprecated",
DESCRIPTION = "description",
EXAMPLE = "example",
FORMAT = "format",
IGNORE = "ignore",
SUMMARY = "summary"
}
//#endregion
//#region src/adapters/typescript/js-doc/module.d.ts
declare function getJSDocDescription(node: Node, index?: number): string | undefined;
declare function getJSDoc(node: Node, index?: number): undefined | JSDoc;
declare function getJSDocTags(node: Node, isMatching?: `${JSDocTagName}` | `${JSDocTagName}`[] | (string & {}) | (string & {})[] | ((tag: JSDocTag) => boolean)): JSDocTag[];
declare function hasJSDocTag(node: Node, tagName: ((tag: JSDocTag) => boolean) | `${JSDocTagName}` | (string & {})): boolean;
declare function getJSDocTagComment(node: Node, tagName: ((tag: JSDocTag) => boolean) | `${JSDocTagName}`): undefined | string;
declare function getJSDocTagNames(node: Node, requireTagName?: boolean): string[];
//#endregion
//#region src/adapters/typescript/js-doc/utils.d.ts
declare function transformJSDocComment(input?: string | NodeArray<JSDocComment>): string | undefined;
//#endregion
//#region src/adapters/typescript/validator/module.d.ts
declare function getDeclarationValidators(declaration: PropertyDeclaration | TypeAliasDeclaration | PropertySignature | ParameterDeclaration, name?: string): Record<string, Validator>;
//#endregion
//#region src/adapters/decorator/orchestrator/types.d.ts
type ApplyHandlersOptions = {
target: DecoratorTarget;
host: DecoratorHost;
resolveTypeNode: (node: TypeNode) => Type;
parameterType?: () => Type | undefined;
typeChecker?: TypeChecker;
/**
* Optional reporter for decorator sources that no handler matched.
* The orchestrator builds a {@link DecoratorSource} for every decorator
* on the node; if iteration finishes without any handler claiming a
* source, this callback fires once for that source.
*/
onUnmatchedDecorator?: (report: UnmatchedDecoratorReport, source: DecoratorSource) => void;
};
//#endregion
//#region src/adapters/decorator/orchestrator/module.d.ts
type DecoratorHandlerLike<D> = {
match: Match;
apply: (ctx: HandlerContext, draft: D) => void;
};
type JsDocHandlerLike<D> = {
match: JsDocMatch;
apply: (ctx: JsDocHandlerContext, draft: D) => void;
};
declare function buildHandlerContext(source: DecoratorSource, options: ApplyHandlersOptions): HandlerContext;
declare function buildJsDocHandlerContext(source: JsDocSource, options: ApplyHandlersOptions): JsDocHandlerContext;
declare function applyDecoratorHandlers<D>(node: Node, handlers: DecoratorHandlerLike<D>[], draft: D, options: ApplyHandlersOptions): void;
declare function applyJsDocHandlers<D>(node: Node, handlers: JsDocHandlerLike<D>[], draft: D, options: ApplyHandlersOptions): void;
//#endregion
//#region src/adapters/decorator/typescript/types.d.ts
type DecoratorSourceBuilderOptions = {
target: DecoratorTarget;
host: DecoratorHost;
resolveTypeNode: (node: TypeNode) => Type;
typeChecker?: TypeChecker;
};
type JsDocSourceBuilderOptions = {
target: DecoratorTarget;
host: DecoratorHost;
resolveTypeNode: (node: TypeNode) => Type;
};
//#endregion
//#region src/adapters/decorator/typescript/module.d.ts
declare function buildDecoratorSources(node: Node, options: DecoratorSourceBuilderOptions): DecoratorSource[];
declare function buildJsDocSources(node: Node, options: JsDocSourceBuilderOptions): JsDocSource[];
//#endregion
//#region src/adapters/decorator/typescript/utils.d.ts
type RawDecorator = {
name: string;
arguments: DecoratorArgument[];
};
/**
* Enumerate decorators on a TS node and classify their argument values without
* going through the registry. Used by read-side consumers (type resolver,
* extension extraction) that only need decorator names + argument values.
*/
declare function readNodeDecorators(node: Node, typeChecker?: TypeChecker): RawDecorator[];
declare function findDecoratorByName(node: Node, name: string, typeChecker?: TypeChecker): RawDecorator | undefined;
declare function findDecoratorsByName(node: Node, name: string, typeChecker?: TypeChecker): RawDecorator[];
declare function hasDecoratorNamed(node: Node, name: string, typeChecker?: TypeChecker): boolean;
declare function buildDecoratorArgument(expr: Expression, typeChecker?: TypeChecker): DecoratorArgument;
//#endregion
//#region src/adapters/filesystem/source-files.d.ts
declare function scanSourceFiles(input: EntryPoint): Promise<string[]>;
//#endregion
//#region src/app/generate.d.ts
declare function generateMetadata(options: MetadataGenerateOptions): Promise<Metadata>;
//#endregion
//#region src/app/generator/metadata/module.d.ts
declare class MetadataGenerator implements IGeneratorContext, IMetadataGenerator {
readonly nodes: Node[];
readonly typeChecker: TypeChecker;
registry: Registry;
readonly resolverCache: ResolverCache;
readonly config: MetadataGeneratorOptions;
private readonly program;
private cache;
private controllers;
private referenceTypes;
private circularDependencyResolvers;
private unmatchedDecorators;
constructor(context: MetadataGeneratorContext);
generate(): Promise<Metadata>;
private assertPresetProducedControllers;
reportUnmatchedDecorator(report: UnmatchedDecoratorReport): void;
private dispatchUnmatchedDecoratorReports;
private formatUnmatchedSummary;
protected buildNodesFromSourceFiles(): string;
/**
* Check if the source file path is in the ignored path list.
*
* @param filePath
* @protected
*/
protected isIgnoredPath(filePath: string): boolean;
/**
* Check if the source file path is in the ignored path list.
*
* @param filePath
* @protected
*/
protected isAllowedPath(filePath: string): boolean;
isExportedNode(_node: Node): boolean;
addReferenceType(referenceType: ReferenceType): void;
getReferenceType(refName: string): ReferenceType | undefined;
registerDependencyResolver(callback: DependencyResolver): void;
private buildControllers;
}
//#endregion
//#region src/app/generator/controller/module.d.ts
declare class ControllerGenerator implements IControllerGenerator {
protected readonly node: ClassDeclaration;
protected readonly current: IGeneratorContext;
constructor(node: ClassDeclaration, current: IGeneratorContext);
isValid(): boolean;
generate(): Controller | null;
private applyOptions;
protected buildMethods(controllerPaths: string[]): Method[];
private collectInheritedMethodDeclarations;
private resolveBaseClassDeclaration;
}
//#endregion
//#region src/app/generator/method/module.d.ts
declare class MethodGenerator {
protected readonly node: MethodDeclaration;
protected readonly current: IGeneratorContext;
constructor(node: MethodDeclaration, current: IGeneratorContext);
getMethodName(): string;
generate(controllerPaths: string[]): Method | null;
private applyOptions;
private resolveReturnType;
private buildParameters;
}
//#endregion
//#region src/app/generator/parameter/module.d.ts
declare class ParameterGenerator implements IParameterGenerator {
private readonly parameter;
private readonly method;
private readonly paths;
private readonly current;
constructor(parameter: ParameterDeclaration, method: string, paths: string[], current: IGeneratorContext);
generate(): Parameter[];
private finalize;
private draftToParameter;
private decomposeObject;
private pathContainsParam;
private validatePathDecomposition;
private validatePathName;
private isLeafTypeSupported;
private isLeafOrEnumOrUnion;
private resolveType;
private getParameterName;
private getDescription;
private getJsDocExamples;
private applyOptions;
}
//#endregion
//#region src/core/utils/array.d.ts
declare function isStringArray(input: unknown): input is string[];
//#endregion
//#region src/core/utils/object.d.ts
declare function hasOwnProperty<Y extends PropertyKey>(obj: unknown, prop: Y): obj is Record<Y, unknown>;
//#endregion
//#region src/core/utils/path-normalize.d.ts
declare function normalizePath(str: string): string;
//#endregion
export { ApplyHandlersOptions, CACHE_DEFAULT_MAX_AGE_MS, CACHE_FILE_PREFIX, CACHE_FILE_SUFFIX, CACHE_SCHEMA_VERSION, CacheClient, CacheData, CacheKeyParts, CacheOptions, CacheOptionsInput, ConfigError, ConfigErrorCode, ControllerGenerator, DecoratorSourceBuilderOptions, EntryPoint, EntryPointOptions, GeneratorError, GeneratorErrorCode, ICacheClient, IGeneratorContext, IMetadataGenerator, IReferenceTypeRegistry, IResolverContext, JSDocTagName, JsDocSourceBuilderOptions, MetadataError, MetadataGenerateOptions, MetadataGenerator, MetadataGeneratorContext, MetadataGeneratorOptions, MethodGenerator, NodeDecorator, OverrideToken, ParameterError, ParameterErrorCode, ParameterGenerator, PrimitiveResolver, RawDecorator, ReferenceResolver, ResolverBase, ResolverCache, ResolverError, SubResolverContext, TsCompilerOptions, TsConfig, TsconfigLoadContext, TypeNodeResolver, TypeNodeResolverContext, UsableDeclaration, ValidatorError, ValidatorErrorCode, applyDecoratorHandlers, applyJsDocHandlers, buildCacheOptions, buildDecoratorArgument, buildDecoratorSources, buildHandlerContext, buildJsDocHandlerContext, buildJsDocSources, composeCacheKey, findDecoratorByName, findDecoratorsByName, generateMetadata, getDeclarationValidators, getInitializerValue, getJSDoc, getJSDocDescription, getJSDocTagComment, getJSDocTagNames, getJSDocTags, getLiteralValue, getNodeDecorators, getNodeDescription, getNodeExtensions, hasDecoratorNamed, hasInitializer, hasJSDocTag, hasOwnProperty, hashCompilerOptions, hashRegistry, isGeneratorError, isResolverError, isStringArray, loadTSConfig, normalizePath, prettyLocationOfNode, prettyTroubleCause, readNodeDecorators, resolveArrayType, resolveIndexedAccessType, resolveIntersectionType, resolveLiteralType, resolveMappedType, resolveObjectLiteralType, resolveTupleType, resolveTypeOperatorType, resolveUnionType, scanSourceFiles, softLoadTsconfig, toTypeNodeOrFail, transformJSDocComment };
//# sourceMappingURL=index.d.mts.map