nestjs-openapi 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import 'tsx';
3
3
  import { Effect, Exit, Cause, Option } from 'effect';
4
- import { ax as generateEffect, ak as generatorServicesLayer, az as runtimeLayerFor, aw as formatValidationResult } from './shared/nestjs-openapi.DeikubMm.mjs';
4
+ import { ax as generateEffect, ak as generatorServicesLayer, az as runtimeLayerFor, aw as formatValidationResult } from './shared/nestjs-openapi.CU_zMKfF.mjs';
5
5
  import minimist from 'minimist';
6
6
  import { relative } from 'node:path';
7
7
  import { createRequire } from 'node:module';
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OpenApiSpec, S as SpecFileNotFoundError, a as SpecFileReadError, b as SpecFileParseError, M as MethodInfo, c as OpenApiPaths, d as OpenApiOperation, e as OpenApiPaths$1, G as GeneratedSchemas, f as OpenApiSchema, g as OutputService, h as SchemaService, V as ValidationService, C as ConfigService, i as ModuleTraversalService, j as MethodExtractionService, P as ProjectService } from './shared/nestjs-openapi.NtbZNAvU.mjs';
2
- export { a4 as AnalysisError, aJ as BrokenRef, aK as BrokenRefCategories, az as ClassValidationInfo, n as Config, a3 as ConfigError, X as ConfigLoadError, W as ConfigNotFoundError, Y as ConfigValidationError, o as ContactConfig, Z as DtoGlobResolutionError, U as EntryNotFoundError, E as GenerateOptions, s as GenerateOverrides, l as GenerateResult, a5 as GeneratorError, J as HttpMethod, I as InfoConfig, _ as InvalidMethodError, am as JsonSchema, L as LicenseConfig, $ as MissingGenericSchemaTempFileCleanupError, a0 as MissingGenericSchemaTempFileWriteError, ac as ModuleWithControllers, K as OpenApiGeneratorConfig, t as OpenApiOperation, u as OpenApiParameter, v as OpenApiRequestBody, w as OpenApiResponse, q as OutputFormat, F as ParameterLocation, a8 as ProjectContext, a2 as ProjectError, Q as ProjectInitError, a9 as ProjectOptions, a6 as ProjectServiceLive, ay as PropertyValidationInfo, a1 as PublicApiError, N as ResolvedConfig, R as ResolvedParameter, H as ReturnTypeInfo, ak as SchemaError, aj as SchemaGenerationError, al as SchemaGeneratorOptions, p as ServerConfig, T as TagConfig, r as TelemetryConfig, ax as ValidationConstraints, aI as ValidationResult, au as applyConstraintsToSchema, aG as categorizeBrokenRefs, m as defineConfig, as as extractClassConstraints, aq as extractClassValidationInfo, ar as extractClassValidationInfoEffect, an as extractPropertyConstraints, ap as extractPropertyValidationInfo, aA as findConfigFile, aH as formatValidationResult, k as generate, y as generateAsync, x as generateEffect, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect, ah as generateSchemas, ai as generateSchemasFromFiles, ab as getAllControllers, af as getControllerMethodInfos, ag as getControllerMethodInfosEffect, ad as getMethodInfo, ae as getMethodInfoEffect, aa as getModules, at as getRequiredProperties, ao as isPropertyOptional, aE as loadAndResolveConfig, aC as loadConfig, aB as loadConfigFromFile, a7 as makeProjectContext, av as mergeValidationConstraints, aw as mergeValidationConstraintsEffect, aD as resolveConfig, aF as validateSpec } from './shared/nestjs-openapi.NtbZNAvU.mjs';
1
+ import { O as OpenApiSpec, S as SpecFileNotFoundError, a as SpecFileReadError, b as SpecFileParseError, M as MethodInfo, c as OpenApiPaths, d as OpenApiOperation, e as OpenApiPaths$1, G as GeneratedSchemas, f as OpenApiSchema, g as SchemaService, h as OutputService, C as ConfigService, i as ModuleTraversalService, j as MethodExtractionService, V as ValidationService, P as ProjectService } from './shared/nestjs-openapi.CDtSgIYg.mjs';
2
+ export { a4 as AnalysisError, aJ as BrokenRef, aK as BrokenRefCategories, az as ClassValidationInfo, n as Config, a3 as ConfigError, X as ConfigLoadError, W as ConfigNotFoundError, Y as ConfigValidationError, o as ContactConfig, Z as DtoGlobResolutionError, U as EntryNotFoundError, E as GenerateOptions, s as GenerateOverrides, l as GenerateResult, a5 as GeneratorError, J as HttpMethod, I as InfoConfig, _ as InvalidMethodError, am as JsonSchema, L as LicenseConfig, $ as MissingGenericSchemaTempFileCleanupError, a0 as MissingGenericSchemaTempFileWriteError, ac as ModuleWithControllers, K as OpenApiGeneratorConfig, t as OpenApiOperation, u as OpenApiParameter, v as OpenApiRequestBody, w as OpenApiResponse, q as OutputFormat, F as ParameterLocation, a8 as ProjectContext, a2 as ProjectError, Q as ProjectInitError, a9 as ProjectOptions, a6 as ProjectServiceLive, ay as PropertyValidationInfo, a1 as PublicApiError, N as ResolvedConfig, R as ResolvedParameter, H as ReturnTypeInfo, ak as SchemaError, aj as SchemaGenerationError, al as SchemaGeneratorOptions, p as ServerConfig, T as TagConfig, r as TelemetryConfig, ax as ValidationConstraints, aI as ValidationResult, au as applyConstraintsToSchema, aG as categorizeBrokenRefs, m as defineConfig, as as extractClassConstraints, aq as extractClassValidationInfo, ar as extractClassValidationInfoEffect, an as extractPropertyConstraints, ap as extractPropertyValidationInfo, aA as findConfigFile, aH as formatValidationResult, k as generate, y as generateAsync, x as generateEffect, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect, ah as generateSchemas, ai as generateSchemasFromFiles, ab as getAllControllers, af as getControllerMethodInfos, ag as getControllerMethodInfosEffect, ad as getMethodInfo, ae as getMethodInfoEffect, aa as getModules, at as getRequiredProperties, ao as isPropertyOptional, aE as loadAndResolveConfig, aC as loadConfig, aB as loadConfigFromFile, a7 as makeProjectContext, av as mergeValidationConstraints, aw as mergeValidationConstraintsEffect, aD as resolveConfig, aF as validateSpec } from './shared/nestjs-openapi.CDtSgIYg.mjs';
3
3
  import { DynamicModule } from '@nestjs/common';
4
4
  import { Effect, Option, Layer } from 'effect';
5
5
  import { ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
@@ -38,10 +38,24 @@ interface SwaggerOptions {
38
38
  */
39
39
  readonly title?: string;
40
40
  }
41
+ interface LoadSpecFileOptions {
42
+ /**
43
+ * Additional spec files to try when the primary file is missing.
44
+ */
45
+ readonly fallbackSpecFiles?: readonly string[];
46
+ }
47
+ interface OpenApiDocumentFileSource extends LoadSpecFileOptions {
48
+ /**
49
+ * Path to the generated OpenAPI JSON file.
50
+ * Can be absolute or relative to the current working directory.
51
+ */
52
+ readonly specFile: string;
53
+ }
54
+ type OpenApiDocumentSource = OpenApiSpec | (() => OpenApiSpec) | OpenApiDocumentFileSource;
41
55
  /**
42
56
  * Configuration options for the OpenAPI module
43
57
  */
44
- interface OpenApiModuleOptions {
58
+ interface OpenApiModuleOptions extends LoadSpecFileOptions {
45
59
  /**
46
60
  * Path to the generated OpenAPI JSON file.
47
61
  * Can be absolute or relative to the current working directory.
@@ -72,6 +86,7 @@ interface OpenApiModuleOptions {
72
86
  */
73
87
  interface ResolvedOpenApiModuleOptions {
74
88
  readonly specFile: string;
89
+ readonly fallbackSpecFiles: readonly string[];
75
90
  readonly enabled: boolean;
76
91
  readonly jsonPath: string;
77
92
  readonly swagger: {
@@ -88,6 +103,52 @@ declare const OPENAPI_MODULE_OPTIONS: unique symbol;
88
103
  * Injection token for the loaded OpenAPI specification
89
104
  */
90
105
  declare const OPENAPI_SPEC: unique symbol;
106
+ interface OpenApiRouteRegistrar {
107
+ readonly get: (path: string, handler: (request: unknown, response: unknown) => void) => void;
108
+ }
109
+ interface OpenApiHttpApplication {
110
+ readonly config?: {
111
+ readonly getGlobalPrefix?: () => string;
112
+ };
113
+ readonly getHttpAdapter: () => OpenApiRouteRegistrar;
114
+ }
115
+ interface OpenApiSetupOptions {
116
+ /**
117
+ * Whether OpenAPI routes should be registered.
118
+ * @default true
119
+ */
120
+ readonly enabled?: boolean;
121
+ /**
122
+ * Prefix OpenAPI routes with the app's `setGlobalPrefix()` value.
123
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.useGlobalPrefix`.
124
+ * @default false
125
+ */
126
+ readonly useGlobalPrefix?: boolean;
127
+ /**
128
+ * Raw OpenAPI JSON endpoint path.
129
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.jsonDocumentUrl`.
130
+ * @default `${docsPath}-json`
131
+ */
132
+ readonly jsonDocumentUrl?: string;
133
+ /**
134
+ * Whether Swagger UI should be served.
135
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.ui`.
136
+ * @default true
137
+ */
138
+ readonly ui?: boolean;
139
+ /**
140
+ * Whether raw OpenAPI definitions should be served.
141
+ * Only JSON is supported.
142
+ * @default true
143
+ */
144
+ readonly raw?: boolean | readonly 'json'[];
145
+ /**
146
+ * Browser title for Swagger UI.
147
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.customSiteTitle`.
148
+ * Uses the spec's info.title if not provided.
149
+ */
150
+ readonly customSiteTitle?: string;
151
+ }
91
152
  /**
92
153
  * Generate Swagger UI HTML page
93
154
  */
@@ -95,8 +156,8 @@ declare function generateSwaggerUiHtml(title: string, jsonPath: string): string;
95
156
  /**
96
157
  * Load the OpenAPI spec file from disk
97
158
  */
98
- declare const loadSpecFileEffect: (filePath: string) => Effect.Effect<OpenApiSpec, SpecFileNotFoundError | SpecFileReadError | SpecFileParseError, never>;
99
- declare function loadSpecFile(filePath: string): OpenApiSpec;
159
+ declare const loadSpecFileEffect: (filePath: string, options?: LoadSpecFileOptions | undefined) => Effect.Effect<OpenApiSpec, SpecFileNotFoundError | SpecFileReadError | SpecFileParseError, never>;
160
+ declare function loadSpecFile(filePath: string, options?: LoadSpecFileOptions): OpenApiSpec;
100
161
  /**
101
162
  * Resolve options with defaults
102
163
  */
@@ -143,6 +204,13 @@ declare class OpenApiModule {
143
204
  * @returns Dynamic module configuration
144
205
  */
145
206
  static forRoot(options: OpenApiModuleOptions): DynamicModule;
207
+ /**
208
+ * Register OpenAPI JSON and Swagger UI routes on an already-created Nest app.
209
+ *
210
+ * Use this when the route config depends on services that are only available
211
+ * during bootstrap. For module-level static config, prefer `forRoot()`.
212
+ */
213
+ static setup(path: string, app: OpenApiHttpApplication, documentSource: OpenApiDocumentSource, options?: OpenApiSetupOptions): void;
146
214
  }
147
215
 
148
216
  declare const normalizePath: (path: string) => string;
@@ -159,10 +227,10 @@ declare const getHttpDecorator: (method: MethodDeclaration) => Decorator | undef
159
227
 
160
228
  declare const transformMethod: (methodInfo: MethodInfo) => OpenApiPaths;
161
229
  declare const transformMethodEffect: (methodInfo: {
162
- readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
163
230
  readonly path: string;
164
- readonly methodName: string;
165
231
  readonly controllerName: string;
232
+ readonly methodName: string;
233
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
166
234
  readonly controllerTags: readonly string[];
167
235
  readonly returnType: {
168
236
  readonly filePath: Option.Option<string>;
@@ -185,8 +253,8 @@ declare const transformMethodEffect: (methodInfo: {
185
253
  readonly deprecated: Option.Option<boolean>;
186
254
  };
187
255
  readonly responses: readonly {
188
- readonly type: Option.Option<string>;
189
256
  readonly description: Option.Option<string>;
257
+ readonly type: Option.Option<string>;
190
258
  readonly statusCode: number;
191
259
  readonly isArray: boolean;
192
260
  }[];
@@ -205,10 +273,10 @@ type MutableOpenApiPaths = {
205
273
  };
206
274
  declare const transformMethods: (methodInfos: readonly MethodInfo[]) => OpenApiPaths;
207
275
  declare const transformMethodsEffect: (methodInfos: readonly {
208
- readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
209
276
  readonly path: string;
210
- readonly methodName: string;
211
277
  readonly controllerName: string;
278
+ readonly methodName: string;
279
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
212
280
  readonly controllerTags: readonly string[];
213
281
  readonly returnType: {
214
282
  readonly filePath: Option.Option<string>;
@@ -231,8 +299,8 @@ declare const transformMethodsEffect: (methodInfos: readonly {
231
299
  readonly deprecated: Option.Option<boolean>;
232
300
  };
233
301
  readonly responses: readonly {
234
- readonly type: Option.Option<string>;
235
302
  readonly description: Option.Option<string>;
303
+ readonly type: Option.Option<string>;
236
304
  readonly statusCode: number;
237
305
  readonly isArray: boolean;
238
306
  }[];
@@ -309,7 +377,7 @@ declare const normalizeStructureRefsEffect: (schemas: GeneratedSchemas) => Effec
309
377
  /**
310
378
  * Shared service dependency graph for generation pipelines.
311
379
  */
312
- declare const generatorServicesLayer: Layer.Layer<OutputService | SchemaService | ValidationService | ConfigService | ModuleTraversalService | MethodExtractionService | ProjectService, never, never>;
380
+ declare const generatorServicesLayer: Layer.Layer<SchemaService | OutputService | ConfigService | ModuleTraversalService | MethodExtractionService | ValidationService | ProjectService, never, never>;
313
381
 
314
382
  /** Handles aliased symbols (re-exports) */
315
383
  declare const resolveClassFromSymbol: (sym: Symbol) => Option.Option<ClassDeclaration>;
@@ -329,4 +397,4 @@ interface ModuleMetadata {
329
397
  declare const getModuleMetadata: (mod: ClassDeclaration) => ModuleMetadata;
330
398
 
331
399
  export { ConfigService, GeneratedSchemas, MethodExtractionService, MethodInfo, ModuleTraversalService, OPENAPI_MODULE_OPTIONS, OPENAPI_SPEC, OpenApiModule, OpenApiPaths$1 as OpenApiPaths, OpenApiSchema, OpenApiSpec, OutputService, ProjectService, SchemaService, SpecFileNotFoundError, SpecFileParseError, SpecFileReadError, ValidationService, filterInternalSchemas, filterInternalSchemasEffect, filterSchemas, filterSchemasEffect, generateSwaggerUiHtml, generatorServicesLayer, getArrayInitializer, getControllerName, getControllerPrefix, getControllerTags, getDecoratorName, getHttpDecorator, getHttpMethods, getModuleDecoratorArg, getModuleMetadata, getStringLiteralValue, getSymbolFromIdentifier, isHttpDecorator, isHttpMethod, isModuleClass, loadSpecFile, loadSpecFileEffect, mergeGeneratedSchemas, mergeGeneratedSchemasEffect, mergeSchemas, mergeSchemasEffect, normalizePath, normalizeSchemas, normalizeSchemasEffect, normalizeStructureRefs, normalizeStructureRefsEffect, resolveArrayOfClasses, resolveClassFromExpression, resolveClassFromSymbol, resolveOptions, toPascalCase, transformMethod, transformMethodEffect, transformMethods, transformMethodsEffect };
332
- export type { MergedResult, ModuleMetadata, NormalizerOptions, OpenApiModuleOptions, ResolvedOpenApiModuleOptions, SwaggerOptions };
400
+ export type { LoadSpecFileOptions, MergedResult, ModuleMetadata, NormalizerOptions, OpenApiDocumentFileSource, OpenApiDocumentSource, OpenApiHttpApplication, OpenApiModuleOptions, OpenApiSetupOptions, ResolvedOpenApiModuleOptions, SwaggerOptions };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OpenApiSpec, S as SpecFileNotFoundError, a as SpecFileReadError, b as SpecFileParseError, M as MethodInfo, c as OpenApiPaths, d as OpenApiOperation, e as OpenApiPaths$1, G as GeneratedSchemas, f as OpenApiSchema, g as OutputService, h as SchemaService, V as ValidationService, C as ConfigService, i as ModuleTraversalService, j as MethodExtractionService, P as ProjectService } from './shared/nestjs-openapi.NtbZNAvU.js';
2
- export { a4 as AnalysisError, aJ as BrokenRef, aK as BrokenRefCategories, az as ClassValidationInfo, n as Config, a3 as ConfigError, X as ConfigLoadError, W as ConfigNotFoundError, Y as ConfigValidationError, o as ContactConfig, Z as DtoGlobResolutionError, U as EntryNotFoundError, E as GenerateOptions, s as GenerateOverrides, l as GenerateResult, a5 as GeneratorError, J as HttpMethod, I as InfoConfig, _ as InvalidMethodError, am as JsonSchema, L as LicenseConfig, $ as MissingGenericSchemaTempFileCleanupError, a0 as MissingGenericSchemaTempFileWriteError, ac as ModuleWithControllers, K as OpenApiGeneratorConfig, t as OpenApiOperation, u as OpenApiParameter, v as OpenApiRequestBody, w as OpenApiResponse, q as OutputFormat, F as ParameterLocation, a8 as ProjectContext, a2 as ProjectError, Q as ProjectInitError, a9 as ProjectOptions, a6 as ProjectServiceLive, ay as PropertyValidationInfo, a1 as PublicApiError, N as ResolvedConfig, R as ResolvedParameter, H as ReturnTypeInfo, ak as SchemaError, aj as SchemaGenerationError, al as SchemaGeneratorOptions, p as ServerConfig, T as TagConfig, r as TelemetryConfig, ax as ValidationConstraints, aI as ValidationResult, au as applyConstraintsToSchema, aG as categorizeBrokenRefs, m as defineConfig, as as extractClassConstraints, aq as extractClassValidationInfo, ar as extractClassValidationInfoEffect, an as extractPropertyConstraints, ap as extractPropertyValidationInfo, aA as findConfigFile, aH as formatValidationResult, k as generate, y as generateAsync, x as generateEffect, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect, ah as generateSchemas, ai as generateSchemasFromFiles, ab as getAllControllers, af as getControllerMethodInfos, ag as getControllerMethodInfosEffect, ad as getMethodInfo, ae as getMethodInfoEffect, aa as getModules, at as getRequiredProperties, ao as isPropertyOptional, aE as loadAndResolveConfig, aC as loadConfig, aB as loadConfigFromFile, a7 as makeProjectContext, av as mergeValidationConstraints, aw as mergeValidationConstraintsEffect, aD as resolveConfig, aF as validateSpec } from './shared/nestjs-openapi.NtbZNAvU.js';
1
+ import { O as OpenApiSpec, S as SpecFileNotFoundError, a as SpecFileReadError, b as SpecFileParseError, M as MethodInfo, c as OpenApiPaths, d as OpenApiOperation, e as OpenApiPaths$1, G as GeneratedSchemas, f as OpenApiSchema, g as SchemaService, h as OutputService, C as ConfigService, i as ModuleTraversalService, j as MethodExtractionService, V as ValidationService, P as ProjectService } from './shared/nestjs-openapi.CDtSgIYg.js';
2
+ export { a4 as AnalysisError, aJ as BrokenRef, aK as BrokenRefCategories, az as ClassValidationInfo, n as Config, a3 as ConfigError, X as ConfigLoadError, W as ConfigNotFoundError, Y as ConfigValidationError, o as ContactConfig, Z as DtoGlobResolutionError, U as EntryNotFoundError, E as GenerateOptions, s as GenerateOverrides, l as GenerateResult, a5 as GeneratorError, J as HttpMethod, I as InfoConfig, _ as InvalidMethodError, am as JsonSchema, L as LicenseConfig, $ as MissingGenericSchemaTempFileCleanupError, a0 as MissingGenericSchemaTempFileWriteError, ac as ModuleWithControllers, K as OpenApiGeneratorConfig, t as OpenApiOperation, u as OpenApiParameter, v as OpenApiRequestBody, w as OpenApiResponse, q as OutputFormat, F as ParameterLocation, a8 as ProjectContext, a2 as ProjectError, Q as ProjectInitError, a9 as ProjectOptions, a6 as ProjectServiceLive, ay as PropertyValidationInfo, a1 as PublicApiError, N as ResolvedConfig, R as ResolvedParameter, H as ReturnTypeInfo, ak as SchemaError, aj as SchemaGenerationError, al as SchemaGeneratorOptions, p as ServerConfig, T as TagConfig, r as TelemetryConfig, ax as ValidationConstraints, aI as ValidationResult, au as applyConstraintsToSchema, aG as categorizeBrokenRefs, m as defineConfig, as as extractClassConstraints, aq as extractClassValidationInfo, ar as extractClassValidationInfoEffect, an as extractPropertyConstraints, ap as extractPropertyValidationInfo, aA as findConfigFile, aH as formatValidationResult, k as generate, y as generateAsync, x as generateEffect, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect, ah as generateSchemas, ai as generateSchemasFromFiles, ab as getAllControllers, af as getControllerMethodInfos, ag as getControllerMethodInfosEffect, ad as getMethodInfo, ae as getMethodInfoEffect, aa as getModules, at as getRequiredProperties, ao as isPropertyOptional, aE as loadAndResolveConfig, aC as loadConfig, aB as loadConfigFromFile, a7 as makeProjectContext, av as mergeValidationConstraints, aw as mergeValidationConstraintsEffect, aD as resolveConfig, aF as validateSpec } from './shared/nestjs-openapi.CDtSgIYg.js';
3
3
  import { DynamicModule } from '@nestjs/common';
4
4
  import { Effect, Option, Layer } from 'effect';
5
5
  import { ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
@@ -38,10 +38,24 @@ interface SwaggerOptions {
38
38
  */
39
39
  readonly title?: string;
40
40
  }
41
+ interface LoadSpecFileOptions {
42
+ /**
43
+ * Additional spec files to try when the primary file is missing.
44
+ */
45
+ readonly fallbackSpecFiles?: readonly string[];
46
+ }
47
+ interface OpenApiDocumentFileSource extends LoadSpecFileOptions {
48
+ /**
49
+ * Path to the generated OpenAPI JSON file.
50
+ * Can be absolute or relative to the current working directory.
51
+ */
52
+ readonly specFile: string;
53
+ }
54
+ type OpenApiDocumentSource = OpenApiSpec | (() => OpenApiSpec) | OpenApiDocumentFileSource;
41
55
  /**
42
56
  * Configuration options for the OpenAPI module
43
57
  */
44
- interface OpenApiModuleOptions {
58
+ interface OpenApiModuleOptions extends LoadSpecFileOptions {
45
59
  /**
46
60
  * Path to the generated OpenAPI JSON file.
47
61
  * Can be absolute or relative to the current working directory.
@@ -72,6 +86,7 @@ interface OpenApiModuleOptions {
72
86
  */
73
87
  interface ResolvedOpenApiModuleOptions {
74
88
  readonly specFile: string;
89
+ readonly fallbackSpecFiles: readonly string[];
75
90
  readonly enabled: boolean;
76
91
  readonly jsonPath: string;
77
92
  readonly swagger: {
@@ -88,6 +103,52 @@ declare const OPENAPI_MODULE_OPTIONS: unique symbol;
88
103
  * Injection token for the loaded OpenAPI specification
89
104
  */
90
105
  declare const OPENAPI_SPEC: unique symbol;
106
+ interface OpenApiRouteRegistrar {
107
+ readonly get: (path: string, handler: (request: unknown, response: unknown) => void) => void;
108
+ }
109
+ interface OpenApiHttpApplication {
110
+ readonly config?: {
111
+ readonly getGlobalPrefix?: () => string;
112
+ };
113
+ readonly getHttpAdapter: () => OpenApiRouteRegistrar;
114
+ }
115
+ interface OpenApiSetupOptions {
116
+ /**
117
+ * Whether OpenAPI routes should be registered.
118
+ * @default true
119
+ */
120
+ readonly enabled?: boolean;
121
+ /**
122
+ * Prefix OpenAPI routes with the app's `setGlobalPrefix()` value.
123
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.useGlobalPrefix`.
124
+ * @default false
125
+ */
126
+ readonly useGlobalPrefix?: boolean;
127
+ /**
128
+ * Raw OpenAPI JSON endpoint path.
129
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.jsonDocumentUrl`.
130
+ * @default `${docsPath}-json`
131
+ */
132
+ readonly jsonDocumentUrl?: string;
133
+ /**
134
+ * Whether Swagger UI should be served.
135
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.ui`.
136
+ * @default true
137
+ */
138
+ readonly ui?: boolean;
139
+ /**
140
+ * Whether raw OpenAPI definitions should be served.
141
+ * Only JSON is supported.
142
+ * @default true
143
+ */
144
+ readonly raw?: boolean | readonly 'json'[];
145
+ /**
146
+ * Browser title for Swagger UI.
147
+ * Matches @nestjs/swagger's `SwaggerCustomOptions.customSiteTitle`.
148
+ * Uses the spec's info.title if not provided.
149
+ */
150
+ readonly customSiteTitle?: string;
151
+ }
91
152
  /**
92
153
  * Generate Swagger UI HTML page
93
154
  */
@@ -95,8 +156,8 @@ declare function generateSwaggerUiHtml(title: string, jsonPath: string): string;
95
156
  /**
96
157
  * Load the OpenAPI spec file from disk
97
158
  */
98
- declare const loadSpecFileEffect: (filePath: string) => Effect.Effect<OpenApiSpec, SpecFileNotFoundError | SpecFileReadError | SpecFileParseError, never>;
99
- declare function loadSpecFile(filePath: string): OpenApiSpec;
159
+ declare const loadSpecFileEffect: (filePath: string, options?: LoadSpecFileOptions | undefined) => Effect.Effect<OpenApiSpec, SpecFileNotFoundError | SpecFileReadError | SpecFileParseError, never>;
160
+ declare function loadSpecFile(filePath: string, options?: LoadSpecFileOptions): OpenApiSpec;
100
161
  /**
101
162
  * Resolve options with defaults
102
163
  */
@@ -143,6 +204,13 @@ declare class OpenApiModule {
143
204
  * @returns Dynamic module configuration
144
205
  */
145
206
  static forRoot(options: OpenApiModuleOptions): DynamicModule;
207
+ /**
208
+ * Register OpenAPI JSON and Swagger UI routes on an already-created Nest app.
209
+ *
210
+ * Use this when the route config depends on services that are only available
211
+ * during bootstrap. For module-level static config, prefer `forRoot()`.
212
+ */
213
+ static setup(path: string, app: OpenApiHttpApplication, documentSource: OpenApiDocumentSource, options?: OpenApiSetupOptions): void;
146
214
  }
147
215
 
148
216
  declare const normalizePath: (path: string) => string;
@@ -159,10 +227,10 @@ declare const getHttpDecorator: (method: MethodDeclaration) => Decorator | undef
159
227
 
160
228
  declare const transformMethod: (methodInfo: MethodInfo) => OpenApiPaths;
161
229
  declare const transformMethodEffect: (methodInfo: {
162
- readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
163
230
  readonly path: string;
164
- readonly methodName: string;
165
231
  readonly controllerName: string;
232
+ readonly methodName: string;
233
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
166
234
  readonly controllerTags: readonly string[];
167
235
  readonly returnType: {
168
236
  readonly filePath: Option.Option<string>;
@@ -185,8 +253,8 @@ declare const transformMethodEffect: (methodInfo: {
185
253
  readonly deprecated: Option.Option<boolean>;
186
254
  };
187
255
  readonly responses: readonly {
188
- readonly type: Option.Option<string>;
189
256
  readonly description: Option.Option<string>;
257
+ readonly type: Option.Option<string>;
190
258
  readonly statusCode: number;
191
259
  readonly isArray: boolean;
192
260
  }[];
@@ -205,10 +273,10 @@ type MutableOpenApiPaths = {
205
273
  };
206
274
  declare const transformMethods: (methodInfos: readonly MethodInfo[]) => OpenApiPaths;
207
275
  declare const transformMethodsEffect: (methodInfos: readonly {
208
- readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
209
276
  readonly path: string;
210
- readonly methodName: string;
211
277
  readonly controllerName: string;
278
+ readonly methodName: string;
279
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
212
280
  readonly controllerTags: readonly string[];
213
281
  readonly returnType: {
214
282
  readonly filePath: Option.Option<string>;
@@ -231,8 +299,8 @@ declare const transformMethodsEffect: (methodInfos: readonly {
231
299
  readonly deprecated: Option.Option<boolean>;
232
300
  };
233
301
  readonly responses: readonly {
234
- readonly type: Option.Option<string>;
235
302
  readonly description: Option.Option<string>;
303
+ readonly type: Option.Option<string>;
236
304
  readonly statusCode: number;
237
305
  readonly isArray: boolean;
238
306
  }[];
@@ -309,7 +377,7 @@ declare const normalizeStructureRefsEffect: (schemas: GeneratedSchemas) => Effec
309
377
  /**
310
378
  * Shared service dependency graph for generation pipelines.
311
379
  */
312
- declare const generatorServicesLayer: Layer.Layer<OutputService | SchemaService | ValidationService | ConfigService | ModuleTraversalService | MethodExtractionService | ProjectService, never, never>;
380
+ declare const generatorServicesLayer: Layer.Layer<SchemaService | OutputService | ConfigService | ModuleTraversalService | MethodExtractionService | ValidationService | ProjectService, never, never>;
313
381
 
314
382
  /** Handles aliased symbols (re-exports) */
315
383
  declare const resolveClassFromSymbol: (sym: Symbol) => Option.Option<ClassDeclaration>;
@@ -329,4 +397,4 @@ interface ModuleMetadata {
329
397
  declare const getModuleMetadata: (mod: ClassDeclaration) => ModuleMetadata;
330
398
 
331
399
  export { ConfigService, GeneratedSchemas, MethodExtractionService, MethodInfo, ModuleTraversalService, OPENAPI_MODULE_OPTIONS, OPENAPI_SPEC, OpenApiModule, OpenApiPaths$1 as OpenApiPaths, OpenApiSchema, OpenApiSpec, OutputService, ProjectService, SchemaService, SpecFileNotFoundError, SpecFileParseError, SpecFileReadError, ValidationService, filterInternalSchemas, filterInternalSchemasEffect, filterSchemas, filterSchemasEffect, generateSwaggerUiHtml, generatorServicesLayer, getArrayInitializer, getControllerName, getControllerPrefix, getControllerTags, getDecoratorName, getHttpDecorator, getHttpMethods, getModuleDecoratorArg, getModuleMetadata, getStringLiteralValue, getSymbolFromIdentifier, isHttpDecorator, isHttpMethod, isModuleClass, loadSpecFile, loadSpecFileEffect, mergeGeneratedSchemas, mergeGeneratedSchemasEffect, mergeSchemas, mergeSchemasEffect, normalizePath, normalizeSchemas, normalizeSchemasEffect, normalizeStructureRefs, normalizeStructureRefsEffect, resolveArrayOfClasses, resolveClassFromExpression, resolveClassFromSymbol, resolveOptions, toPascalCase, transformMethod, transformMethodEffect, transformMethods, transformMethodsEffect };
332
- export type { MergedResult, ModuleMetadata, NormalizerOptions, OpenApiModuleOptions, ResolvedOpenApiModuleOptions, SwaggerOptions };
400
+ export type { LoadSpecFileOptions, MergedResult, ModuleMetadata, NormalizerOptions, OpenApiDocumentFileSource, OpenApiDocumentSource, OpenApiHttpApplication, OpenApiModuleOptions, OpenApiSetupOptions, ResolvedOpenApiModuleOptions, SwaggerOptions };
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { S as SpecFileNotFoundError, a as SpecFileReadError, b as SpecFileParseError } from './shared/nestjs-openapi.DeikubMm.mjs';
2
- export { c as ConfigLoadError, C as ConfigNotFoundError, ae as ConfigService, e as ConfigValidationError, D as DtoGlobResolutionError, E as EntryNotFoundError, I as InvalidMethodError, B as MethodExtractionService, M as MissingGenericSchemaTempFileCleanupError, f as MissingGenericSchemaTempFileWriteError, n as ModuleTraversalService, ad as OutputService, P as ProjectInitError, i as ProjectService, j as ProjectServiceLive, h as PublicApiError, a0 as SchemaGenerationError, a1 as SchemaService, ac as ValidationService, a9 as applyConstraintsToSchema, av as categorizeBrokenRefs, d as defineConfig, a7 as extractClassConstraints, a5 as extractClassValidationInfo, a6 as extractClassValidationInfoEffect, a2 as extractPropertyConstraints, a4 as extractPropertyValidationInfo, V as filterInternalSchemas, W as filterInternalSchemasEffect, Q as filterSchemas, R as filterSchemasEffect, af as findConfigFile, aw as formatValidationResult, g as generate, _ as generateSchemas, $ as generateSchemasFromFiles, ak as generatorServicesLayer, l as getAllControllers, am as getArrayInitializer, z as getControllerMethodInfos, A as getControllerMethodInfosEffect, p as getControllerName, o as getControllerPrefix, t as getControllerTags, s as getDecoratorName, u as getHttpDecorator, r as getHttpMethods, x as getMethodInfo, y as getMethodInfoEffect, aq as getModuleDecoratorArg, at as getModuleMetadata, k as getModules, a8 as getRequiredProperties, an as getStringLiteralValue, ao as getSymbolFromIdentifier, v as isHttpDecorator, q as isHttpMethod, ap as isModuleClass, a3 as isPropertyOptional, aj as loadAndResolveConfig, ah as loadConfig, ag as loadConfigFromFile, m as makeProjectContext, N as mergeGeneratedSchemas, O as mergeGeneratedSchemasEffect, K as mergeSchemas, L as mergeSchemasEffect, aa as mergeValidationConstraints, ab as mergeValidationConstraintsEffect, w as normalizePath, T as normalizeSchemas, U as normalizeSchemasEffect, X as normalizeStructureRefs, Y as normalizeStructureRefsEffect, as as resolveArrayOfClasses, ar as resolveClassFromExpression, al as resolveClassFromSymbol, ai as resolveConfig, Z as toPascalCase, F as transformMethod, G as transformMethodEffect, H as transformMethods, J as transformMethodsEffect, au as validateSpec } from './shared/nestjs-openapi.DeikubMm.mjs';
1
+ import { S as SpecFileNotFoundError, a as SpecFileParseError, b as SpecFileReadError } from './shared/nestjs-openapi.CU_zMKfF.mjs';
2
+ export { c as ConfigLoadError, C as ConfigNotFoundError, ae as ConfigService, e as ConfigValidationError, D as DtoGlobResolutionError, E as EntryNotFoundError, I as InvalidMethodError, B as MethodExtractionService, M as MissingGenericSchemaTempFileCleanupError, f as MissingGenericSchemaTempFileWriteError, n as ModuleTraversalService, ad as OutputService, P as ProjectInitError, i as ProjectService, j as ProjectServiceLive, h as PublicApiError, a0 as SchemaGenerationError, a1 as SchemaService, ac as ValidationService, a9 as applyConstraintsToSchema, av as categorizeBrokenRefs, d as defineConfig, a7 as extractClassConstraints, a5 as extractClassValidationInfo, a6 as extractClassValidationInfoEffect, a2 as extractPropertyConstraints, a4 as extractPropertyValidationInfo, V as filterInternalSchemas, W as filterInternalSchemasEffect, Q as filterSchemas, R as filterSchemasEffect, af as findConfigFile, aw as formatValidationResult, g as generate, _ as generateSchemas, $ as generateSchemasFromFiles, ak as generatorServicesLayer, l as getAllControllers, am as getArrayInitializer, z as getControllerMethodInfos, A as getControllerMethodInfosEffect, p as getControllerName, o as getControllerPrefix, t as getControllerTags, s as getDecoratorName, u as getHttpDecorator, r as getHttpMethods, x as getMethodInfo, y as getMethodInfoEffect, aq as getModuleDecoratorArg, at as getModuleMetadata, k as getModules, a8 as getRequiredProperties, an as getStringLiteralValue, ao as getSymbolFromIdentifier, v as isHttpDecorator, q as isHttpMethod, ap as isModuleClass, a3 as isPropertyOptional, aj as loadAndResolveConfig, ah as loadConfig, ag as loadConfigFromFile, m as makeProjectContext, N as mergeGeneratedSchemas, O as mergeGeneratedSchemasEffect, K as mergeSchemas, L as mergeSchemasEffect, aa as mergeValidationConstraints, ab as mergeValidationConstraintsEffect, w as normalizePath, T as normalizeSchemas, U as normalizeSchemasEffect, X as normalizeStructureRefs, Y as normalizeStructureRefsEffect, as as resolveArrayOfClasses, ar as resolveClassFromExpression, al as resolveClassFromSymbol, ai as resolveConfig, Z as toPascalCase, F as transformMethod, G as transformMethodEffect, H as transformMethods, J as transformMethodsEffect, au as validateSpec } from './shared/nestjs-openapi.CU_zMKfF.mjs';
3
3
  import { readFileSync } from 'node:fs';
4
4
  import { fail } from 'node:assert';
5
5
  import { resolve } from 'node:path';
6
6
  import { Module } from '@nestjs/common';
7
- import { Effect, Exit, Cause, Option } from 'effect';
7
+ import { Effect, Either, Exit, Cause, Option } from 'effect';
8
8
  export { generateAsync, generate as generateEffect, generateFromConfigAsync, generateFromConfigEffect, generatePathsAsync, generatePathsEffect } from './internal.mjs';
9
9
  import 'node:crypto';
10
10
  import 'ts-morph';
@@ -94,21 +94,40 @@ function generateSwaggerUiHtml(title, jsonPath) {
94
94
  </body>
95
95
  </html>`;
96
96
  }
97
+ function isErrorWithCode(cause, code) {
98
+ return cause !== null && typeof cause === "object" && "code" in cause && cause.code === code;
99
+ }
100
+ function getSpecFileCandidates(filePath, options = {}) {
101
+ const candidates = [filePath];
102
+ candidates.push(...options.fallbackSpecFiles ?? []);
103
+ return [...new Set(candidates)];
104
+ }
105
+ const readSpecFileContentEffect = (filePath) => Effect.try({
106
+ try: () => readFileSync(resolve(process.cwd(), filePath), "utf-8"),
107
+ catch: (cause) => isErrorWithCode(cause, "ENOENT") ? SpecFileNotFoundError.create(filePath) : SpecFileReadError.create(filePath, cause)
108
+ });
97
109
  const loadSpecFileEffect = Effect.fn("OpenApiModule.loadSpecFile")(
98
- function* (filePath) {
99
- const resolvedPath = resolve(process.cwd(), filePath);
100
- const content = yield* Effect.try({
101
- try: () => readFileSync(resolvedPath, "utf-8"),
102
- catch: (cause) => cause && typeof cause === "object" && "code" in cause && cause.code === "ENOENT" ? SpecFileNotFoundError.create(filePath) : SpecFileReadError.create(filePath, cause)
103
- });
104
- return yield* Effect.try({
105
- try: () => JSON.parse(content),
106
- catch: (cause) => SpecFileParseError.create(filePath, cause)
107
- });
110
+ function* (filePath, options = {}) {
111
+ for (const candidate of getSpecFileCandidates(filePath, options)) {
112
+ const contentResult = yield* readSpecFileContentEffect(candidate).pipe(
113
+ Effect.either
114
+ );
115
+ if (Either.isLeft(contentResult)) {
116
+ if (contentResult.left instanceof SpecFileNotFoundError) {
117
+ continue;
118
+ }
119
+ return yield* Effect.fail(contentResult.left);
120
+ }
121
+ return yield* Effect.try({
122
+ try: () => JSON.parse(contentResult.right),
123
+ catch: (cause) => SpecFileParseError.create(candidate, cause)
124
+ });
125
+ }
126
+ return yield* Effect.fail(SpecFileNotFoundError.create(filePath));
108
127
  }
109
128
  );
110
- function loadSpecFile(filePath) {
111
- const exit = Effect.runSyncExit(loadSpecFileEffect(filePath));
129
+ function loadSpecFile(filePath, options = {}) {
130
+ const exit = Effect.runSyncExit(loadSpecFileEffect(filePath, options));
112
131
  if (Exit.isSuccess(exit)) {
113
132
  return exit.value;
114
133
  }
@@ -131,6 +150,7 @@ function resolveOptions(options) {
131
150
  }
132
151
  return {
133
152
  specFile: options.specFile,
153
+ fallbackSpecFiles: options.fallbackSpecFiles ?? [],
134
154
  enabled: options.enabled ?? true,
135
155
  jsonPath: options.jsonPath ?? "/openapi.json",
136
156
  swagger: {
@@ -140,6 +160,26 @@ function resolveOptions(options) {
140
160
  }
141
161
  };
142
162
  }
163
+ function resolveOptionsWithSpecTitle(options, spec) {
164
+ return {
165
+ ...options,
166
+ swagger: {
167
+ ...options.swagger,
168
+ title: options.swagger.title || spec.info.title
169
+ }
170
+ };
171
+ }
172
+ function createOpenApiModuleState(options) {
173
+ const resolvedOptions = resolveOptions(options);
174
+ if (!resolvedOptions.enabled) {
175
+ return { options: resolvedOptions };
176
+ }
177
+ const spec = loadSpecFile(resolvedOptions.specFile, resolvedOptions);
178
+ return {
179
+ spec,
180
+ options: resolveOptionsWithSpecTitle(resolvedOptions, spec)
181
+ };
182
+ }
143
183
  _OpenApiModule_decorators = [Module({})];
144
184
  let _OpenApiModule = class _OpenApiModule {
145
185
  /**
@@ -149,8 +189,8 @@ let _OpenApiModule = class _OpenApiModule {
149
189
  * @returns Dynamic module configuration
150
190
  */
151
191
  static forRoot(options) {
152
- const resolvedOptions = resolveOptions(options);
153
- if (!resolvedOptions.enabled) {
192
+ const state = createOpenApiModuleState(options);
193
+ if (!state.options.enabled || !state.spec) {
154
194
  return {
155
195
  module: _OpenApiModule,
156
196
  providers: [],
@@ -158,25 +198,17 @@ let _OpenApiModule = class _OpenApiModule {
158
198
  exports: []
159
199
  };
160
200
  }
161
- const spec = loadSpecFile(resolvedOptions.specFile);
162
- const finalOptions = {
163
- ...resolvedOptions,
164
- swagger: {
165
- ...resolvedOptions.swagger,
166
- title: resolvedOptions.swagger.title || spec.info.title
167
- }
168
- };
169
201
  const providers = [
170
202
  {
171
203
  provide: OPENAPI_MODULE_OPTIONS,
172
- useValue: finalOptions
204
+ useValue: state.options
173
205
  },
174
206
  {
175
207
  provide: OPENAPI_SPEC,
176
- useValue: spec
208
+ useValue: state.spec
177
209
  }
178
210
  ];
179
- const controllers = createOpenApiControllers(finalOptions, spec);
211
+ const controllers = createOpenApiControllers(state.options, state.spec);
180
212
  return {
181
213
  module: _OpenApiModule,
182
214
  providers,
@@ -184,11 +216,97 @@ let _OpenApiModule = class _OpenApiModule {
184
216
  exports: [OPENAPI_MODULE_OPTIONS, OPENAPI_SPEC]
185
217
  };
186
218
  }
219
+ /**
220
+ * Register OpenAPI JSON and Swagger UI routes on an already-created Nest app.
221
+ *
222
+ * Use this when the route config depends on services that are only available
223
+ * during bootstrap. For module-level static config, prefer `forRoot()`.
224
+ */
225
+ static setup(path, app, documentSource, options = {}) {
226
+ if (options.enabled === false) {
227
+ return;
228
+ }
229
+ const spec = loadDocumentSource(documentSource);
230
+ const httpAdapter = app.getHttpAdapter();
231
+ const swaggerPath = resolveSetupPath(path, app, options);
232
+ const jsonPath = resolveJsonDocumentUrl(swaggerPath, app, options);
233
+ if (shouldServeJson(options.raw)) {
234
+ httpAdapter.get(jsonPath, (_request, response) => {
235
+ sendResponse(response, spec, "application/json");
236
+ });
237
+ }
238
+ if (options.ui !== false) {
239
+ httpAdapter.get(swaggerPath, (_request, response) => {
240
+ sendResponse(
241
+ response,
242
+ generateSwaggerUiHtml(
243
+ options.customSiteTitle ?? spec.info.title,
244
+ jsonPath
245
+ ),
246
+ "text/html"
247
+ );
248
+ });
249
+ }
250
+ }
187
251
  };
188
252
  _init = __decoratorStart();
189
253
  _OpenApiModule = __decorateElement(_init, 0, "OpenApiModule", _OpenApiModule_decorators, _OpenApiModule);
190
254
  __runInitializers(_init, 1, _OpenApiModule);
191
255
  let OpenApiModule = _OpenApiModule;
256
+ function loadDocumentSource(source) {
257
+ if (typeof source === "function") {
258
+ return source();
259
+ }
260
+ if (isDocumentFileSource(source)) {
261
+ return loadSpecFile(source.specFile, source);
262
+ }
263
+ return source;
264
+ }
265
+ function isDocumentFileSource(source) {
266
+ return source !== null && typeof source === "object" && "specFile" in source && typeof source.specFile === "string";
267
+ }
268
+ function resolveSetupPath(path, app, options) {
269
+ return joinRoutePath(
270
+ options.useGlobalPrefix === true ? getGlobalPrefix(app) : void 0,
271
+ path
272
+ );
273
+ }
274
+ function resolveJsonDocumentUrl(finalSwaggerPath, app, options) {
275
+ if (!options.jsonDocumentUrl) {
276
+ return `${finalSwaggerPath}-json`;
277
+ }
278
+ return joinRoutePath(
279
+ options.useGlobalPrefix === true ? getGlobalPrefix(app) : void 0,
280
+ options.jsonDocumentUrl
281
+ );
282
+ }
283
+ function getGlobalPrefix(app) {
284
+ const appWithConfig = app;
285
+ return appWithConfig.config?.getGlobalPrefix?.() ?? "";
286
+ }
287
+ function shouldServeJson(raw) {
288
+ return raw === void 0 || raw === true || Array.isArray(raw) && raw.length > 0;
289
+ }
290
+ function joinRoutePath(...parts) {
291
+ return `/${parts.filter((part) => part !== void 0 && part !== "").map((part) => part.replace(/^\/+|\/+$/g, "")).filter((part) => part.length > 0).join("/")}`;
292
+ }
293
+ function sendResponse(response, body, contentType) {
294
+ const responseLike = response;
295
+ responseLike.setHeader?.("Content-Type", contentType);
296
+ if (contentType === "application/json" && responseLike.json) {
297
+ responseLike.json(body);
298
+ return;
299
+ }
300
+ if (responseLike.type && responseLike.send) {
301
+ responseLike.type(contentType).send(body);
302
+ return;
303
+ }
304
+ if (responseLike.send) {
305
+ responseLike.send(body);
306
+ return;
307
+ }
308
+ responseLike.end?.(typeof body === "string" ? body : JSON.stringify(body));
309
+ }
192
310
  function createJsonController(controllerPath, spec) {
193
311
  class JsonSpecController {
194
312
  getSpec() {
@@ -1,3 +1,3 @@
1
- export { E as GenerateOptions, x as generate, y as generateAsync, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect } from './shared/nestjs-openapi.NtbZNAvU.mjs';
1
+ export { E as GenerateOptions, x as generate, y as generateAsync, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect } from './shared/nestjs-openapi.CDtSgIYg.mjs';
2
2
  import 'effect';
3
3
  import 'ts-morph';
@@ -1,3 +1,3 @@
1
- export { E as GenerateOptions, x as generate, y as generateAsync, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect } from './shared/nestjs-openapi.NtbZNAvU.js';
1
+ export { E as GenerateOptions, x as generate, y as generateAsync, D as generateFromConfigAsync, B as generateFromConfigEffect, A as generatePathsAsync, z as generatePathsEffect } from './shared/nestjs-openapi.CDtSgIYg.js';
2
2
  import 'effect';
3
3
  import 'ts-morph';
package/dist/internal.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Effect } from 'effect';
2
- import { i as ProjectService, n as ModuleTraversalService, B as MethodExtractionService, J as transformMethodsEffect, ax as generateEffect, ay as runProjectApiPromise, ak as generatorServicesLayer, az as runtimeLayerFor, aA as runGeneratorApiPromise } from './shared/nestjs-openapi.DeikubMm.mjs';
2
+ import { i as ProjectService, n as ModuleTraversalService, B as MethodExtractionService, J as transformMethodsEffect, ax as generateEffect, ay as runProjectApiPromise, ak as generatorServicesLayer, az as runtimeLayerFor, aA as runGeneratorApiPromise } from './shared/nestjs-openapi.CU_zMKfF.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:path';
5
5
  import 'node:crypto';