import type { FastifyCorsOptions } from '@fastify/cors'; import type { FastifyHelmetOptions } from '@fastify/helmet'; import type { FastifyDynamicSwaggerOptions } from '@fastify/swagger'; import { FastifySwaggerUiConfigOptions, FastifySwaggerUiOptions } from '@fastify/swagger-ui'; import type { RateLimitPluginOptions } from '@fastify/rate-limit'; import { FastifyInstance, FastifyRequest, FastifyServerOptions } from "fastify"; import { FastifyStaticOptions } from '@fastify/static'; import { FastifyMultipartAttachFieldsToBodyOptions, FastifyMultipartBaseOptions } from '@fastify/multipart'; import { TObject } from '@sinclair/typebox'; import { AppConfig } from './config-loader.js'; import { RouteBuilder, StatusSchemas } from './route.js'; export type UploadFile = { fieldname: string; filename: string; encoding: string; mimetype: string; filesize: number; buffer: Buffer | Buffer; url?: string; meta?: Record; id: string; s3bucket?: string; s3region?: string; } export type FileLoader = (file: UploadFile, routeBuilder: RouteBuilder) => Promise | UploadFile; export type AppOptionHandler = (defaultOptions: T) => T; export interface AppOptions> { apiDir?: string; configSchema?: TObject; logger?: boolean; fileLoader?: FileLoader; fastifyOptions?: AppOptionHandler; corsOptions?: FastifyCorsOptions | boolean | AppOptionHandler; helmetOptions?: FastifyHelmetOptions | boolean | AppOptionHandler; rateLimitOptions?: RateLimitPluginOptions | boolean | AppOptionHandler; swaggerOptions?: AppOptionHandler | FastifyDynamicSwaggerOptions; swaggerUiOptions?: AppOptionHandler | FastifySwaggerUiOptions; staticOptions?: AppOptionHandler | FastifyStaticOptions | boolean; multipartOptions?: AppOptionHandler | FastifyMultipartAttachFieldsToBodyOptions; plugins?: AppPlugin[]; /** * Legacy option: Enable automatic schema registration from .schemas.ts files * * @default false - By default, only explicitly registered schemas (via addSchema()) are registered * * When enabled, automatically scans and registers all schemas with $id from .schemas.ts files. * This is a legacy feature for backward compatibility. New projects should use addSchema() explicitly. * * @example * ```typescript * // Enable legacy auto-registration * createApp({ * legacyAutoSchemaRegistration: true * }); * ``` */ legacyAutoSchemaRegistration?: boolean; /** * Enable logging of duplicate schema structure warnings * * @default false - Duplicate warnings are disabled by default * * When enabled, the schema registry will log warnings when it detects schemas with identical structures. * This can be useful for identifying opportunities to create shared schemas and reduce duplication. * * @example * ```typescript * // Enable duplicate schema warnings * createApp({ * logDuplicateSchemas: true * }); * ``` */ logDuplicateSchemas?: boolean; onInit?(ctx: AppContext): Promise | void; beforeStart?(ctx: AppContext): Promise | void; preReady?(ctx: AppContext): Promise | void; afterStart?(ctx: AppContext): Promise | void; } export type Env = 'production' | 'development'; export interface AppContext> { fastify: FastifyInstance; environment: Env; appDir: string; options: AppOptions; fileLoader?: FileLoader; projectConfig: AppConfig; projectPackage: Record; plugins?: Record; useRoute: (controller?: string) => RouteBuilder; } export type Constructor = new (...args: any[]) => T; export interface AppPlugin, P extends object = Record> { name: string; services?: Constructor[]; config?: P; onInit?(ctx: AppContext): Promise | void; beforeStart?(ctx: AppContext): Promise | void; afterStart?(ctx: AppContext): Promise | void; preReady?(ctx: AppContext): Promise | void; } export type AppMainOptions = { PORT?: number; HOST?: string; APP_NAME?: string; APP_VERSION?: string; }