nestjs-openapi 0.1.4 → 0.2.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/index.d.mts CHANGED
@@ -1,696 +1,8 @@
1
- import { Effect, Context, Layer, Option } from 'effect';
2
- import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.ClTIhsb-.mjs';
3
- export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.ClTIhsb-.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, C as ConfigService, P as ProjectService, g as ModuleTraversalService, h as MethodExtractionService, i as SchemaService, V as ValidationService, j as OutputService } from './shared/nestjs-openapi.C1csrdEX.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.C1csrdEX.mjs';
4
3
  import { DynamicModule } from '@nestjs/common';
5
- import { Project, SourceFile, ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
6
-
7
- /**
8
- * Public types for nestjs-openapi
9
- *
10
- * These types are exposed to consumers of the library. Internal types
11
- * should be kept in domain.ts.
12
- */
13
- /**
14
- * Contact information for the API
15
- */
16
- interface ContactConfig {
17
- readonly name?: string;
18
- readonly email?: string;
19
- readonly url?: string;
20
- }
21
- /**
22
- * License information for the API
23
- */
24
- interface LicenseConfig {
25
- readonly name: string;
26
- readonly url?: string;
27
- }
28
- /**
29
- * API metadata for the OpenAPI info section
30
- */
31
- interface InfoConfig {
32
- readonly title: string;
33
- readonly version: string;
34
- readonly description?: string;
35
- readonly contact?: ContactConfig;
36
- readonly license?: LicenseConfig;
37
- }
38
- /**
39
- * Server configuration for the OpenAPI servers section
40
- */
41
- interface ServerConfig {
42
- readonly url: string;
43
- readonly description?: string;
44
- }
45
- /**
46
- * Tag configuration for organizing API endpoints
47
- */
48
- interface TagConfig {
49
- readonly name: string;
50
- readonly description?: string;
51
- }
52
- /**
53
- * Security scheme type for OpenAPI 3.0
54
- */
55
- type SecuritySchemeType = 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
56
- /**
57
- * Location for apiKey security schemes
58
- */
59
- type SecuritySchemeIn = 'query' | 'header' | 'cookie';
60
- /**
61
- * OAuth2 flow configuration
62
- */
63
- interface OAuth2FlowConfig {
64
- readonly authorizationUrl?: string;
65
- readonly tokenUrl?: string;
66
- readonly refreshUrl?: string;
67
- readonly scopes?: Record<string, string>;
68
- }
69
- /**
70
- * OAuth2 flows configuration
71
- */
72
- interface OAuth2FlowsConfig {
73
- readonly implicit?: OAuth2FlowConfig;
74
- readonly password?: OAuth2FlowConfig;
75
- readonly clientCredentials?: OAuth2FlowConfig;
76
- readonly authorizationCode?: OAuth2FlowConfig;
77
- }
78
- /**
79
- * Security scheme configuration for OpenAPI 3.0
80
- *
81
- * @example
82
- * ```typescript
83
- * // Bearer token (JWT)
84
- * {
85
- * name: 'bearerAuth',
86
- * type: 'http',
87
- * scheme: 'bearer',
88
- * bearerFormat: 'JWT',
89
- * }
90
- *
91
- * // API Key in header
92
- * {
93
- * name: 'apiKey',
94
- * type: 'apiKey',
95
- * in: 'header',
96
- * parameterName: 'X-API-Key',
97
- * }
98
- *
99
- * // OAuth2
100
- * {
101
- * name: 'oauth2',
102
- * type: 'oauth2',
103
- * flows: {
104
- * authorizationCode: {
105
- * authorizationUrl: 'https://example.com/oauth/authorize',
106
- * tokenUrl: 'https://example.com/oauth/token',
107
- * scopes: { 'read:users': 'Read user data' },
108
- * },
109
- * },
110
- * }
111
- * ```
112
- */
113
- interface SecuritySchemeConfig {
114
- /** Unique name for this security scheme (used as key in securitySchemes) */
115
- readonly name: string;
116
- /** The type of the security scheme */
117
- readonly type: SecuritySchemeType;
118
- /** Description of the security scheme */
119
- readonly description?: string;
120
- /** The name of the HTTP Authorization scheme (for type: 'http') */
121
- readonly scheme?: string;
122
- /** A hint for the format of the token (for type: 'http' with scheme: 'bearer') */
123
- readonly bearerFormat?: string;
124
- /** The location of the API key (for type: 'apiKey') */
125
- readonly in?: SecuritySchemeIn;
126
- /** The name of the header, query, or cookie parameter (for type: 'apiKey') */
127
- readonly parameterName?: string;
128
- /** OAuth2 flows configuration (for type: 'oauth2') */
129
- readonly flows?: OAuth2FlowsConfig;
130
- /** OpenID Connect URL to discover OAuth2 config (for type: 'openIdConnect') */
131
- readonly openIdConnectUrl?: string;
132
- }
133
- /**
134
- * Security requirement - maps security scheme names to required scopes
135
- *
136
- * @example
137
- * ```typescript
138
- * // Require bearerAuth with no specific scopes
139
- * { bearerAuth: [] }
140
- *
141
- * // Require oauth2 with specific scopes
142
- * { oauth2: ['read:users', 'write:users'] }
143
- * ```
144
- */
145
- type SecurityRequirement = Record<string, readonly string[]>;
146
- /**
147
- * Output format for the generated OpenAPI specification
148
- */
149
- type OutputFormat = 'json' | 'yaml';
150
- /**
151
- * OpenAPI specification version
152
- * - '3.0.3': OpenAPI 3.0.3 (default, widely supported)
153
- * - '3.1.0': OpenAPI 3.1.0 (full JSON Schema 2020-12 alignment, type arrays for nullable)
154
- * - '3.2.0': OpenAPI 3.2.0 (when released, will include webhooks and other new features)
155
- */
156
- type OpenApiVersion = '3.0.3' | '3.1.0' | '3.2.0';
157
- /**
158
- * Input file configuration for nestjs-openapi.
159
- * All paths are relative to the config file location.
160
- */
161
- interface FilesConfig {
162
- /**
163
- * Entry module file(s).
164
- * @default "src/app.module.ts"
165
- */
166
- readonly entry?: string | readonly string[];
167
- /**
168
- * Path to tsconfig.json. Auto-detected if not specified.
169
- */
170
- readonly tsconfig?: string;
171
- /**
172
- * Glob pattern(s) for DTO files to generate schemas from.
173
- * @example "src/**\/*.dto.ts"
174
- */
175
- readonly dtoGlob?: string | readonly string[];
176
- /**
177
- * Glob patterns to include.
178
- */
179
- readonly include?: readonly string[];
180
- /**
181
- * Glob patterns to exclude.
182
- * @default ["**\/*.spec.ts", "**\/*.test.ts", "**\/node_modules/**"]
183
- */
184
- readonly exclude?: readonly string[];
185
- }
186
- /**
187
- * Security configuration for OpenAPI spec.
188
- */
189
- interface SecurityConfig {
190
- /**
191
- * Security schemes available for the API.
192
- * Defines authentication methods (bearer, apiKey, oauth2, etc.)
193
- */
194
- readonly schemes?: readonly SecuritySchemeConfig[];
195
- /**
196
- * Global security requirements applied to all operations.
197
- * Can be overridden at the operation level.
198
- * Each object in the array represents an alternative (OR logic).
199
- * Within each object, all schemes must be satisfied (AND logic).
200
- *
201
- * @example
202
- * ```typescript
203
- * // Require bearerAuth for all operations
204
- * global: [{ bearerAuth: [] }]
205
- *
206
- * // Allow either bearerAuth OR apiKey
207
- * global: [{ bearerAuth: [] }, { apiKey: [] }]
208
- * ```
209
- */
210
- readonly global?: readonly SecurityRequirement[];
211
- }
212
- /**
213
- * OpenAPI specification metadata configuration.
214
- * Maps directly to the OpenAPI spec structure.
215
- */
216
- interface OpenApiConfig {
217
- /**
218
- * OpenAPI specification version.
219
- * @default "3.0.3"
220
- */
221
- readonly version?: OpenApiVersion;
222
- /**
223
- * API metadata for the info section.
224
- * @required
225
- */
226
- readonly info: InfoConfig;
227
- /**
228
- * Server URLs for the API.
229
- */
230
- readonly servers?: readonly ServerConfig[];
231
- /**
232
- * Tags for organizing API endpoints.
233
- */
234
- readonly tags?: readonly TagConfig[];
235
- /**
236
- * Security configuration.
237
- */
238
- readonly security?: SecurityConfig;
239
- }
240
- /**
241
- * Generation behavior options.
242
- */
243
- interface OptionsConfig {
244
- /**
245
- * Base path prefix for all routes.
246
- * Equivalent to NestJS's app.setGlobalPrefix().
247
- * @example "/api/v1"
248
- */
249
- readonly basePath?: string;
250
- /**
251
- * Extract validation constraints from class-validator decorators.
252
- * @default true
253
- */
254
- readonly extractValidation?: boolean;
255
- /**
256
- * Decorator names that exclude endpoints from the spec.
257
- * @default ["ApiExcludeEndpoint", "ApiExcludeController"]
258
- */
259
- readonly excludeDecorators?: readonly string[];
260
- /**
261
- * Filter paths by regex or predicate function.
262
- * Paths matching the regex (or returning true) are INCLUDED.
263
- *
264
- * @example
265
- * ```typescript
266
- * // Exclude internal and versioned paths
267
- * pathFilter: /^(?!.*(\/internal\/|\/v[\d.]+\/)).* /
268
- *
269
- * // Using a function
270
- * pathFilter: (path) => !path.includes('/internal/')
271
- * ```
272
- */
273
- readonly pathFilter?: RegExp | ((path: string) => boolean);
274
- /**
275
- * Query parameter handling options.
276
- */
277
- readonly query?: QueryOptions;
278
- /**
279
- * Schema generation and normalization options.
280
- */
281
- readonly schemas?: SchemaOptions;
282
- }
283
- /**
284
- * Schema generation and normalization options.
285
- */
286
- interface SchemaOptions {
287
- /**
288
- * How to handle schema aliases that only redirect via `$ref`.
289
- * - `"collapse"`: Rewrite refs to the final target schema and remove alias entries
290
- * - `"preserve"`: Keep alias schemas as-is
291
- *
292
- * @default "collapse"
293
- */
294
- readonly aliasRefs?: 'collapse' | 'preserve';
295
- }
296
- /**
297
- * Query parameter handling options.
298
- */
299
- interface QueryOptions {
300
- /**
301
- * How to represent query object DTOs (e.g., `@Query() dto: PaginationDto`).
302
- * - `"inline"` (default): Expand DTO properties as individual query parameters
303
- * - `"ref"`: Keep as a single parameter with a schema reference
304
- *
305
- * @default "inline"
306
- *
307
- * @example
308
- * ```typescript
309
- * // With style: "inline" (default)
310
- * // @Query() dto: PaginationDto becomes:
311
- * // - page: integer (query)
312
- * // - limit: integer (query)
313
- *
314
- * // With style: "ref"
315
- * // @Query() dto: PaginationDto becomes:
316
- * // - dto: $ref to PaginationDto schema (query)
317
- * ```
318
- */
319
- readonly style?: 'inline' | 'ref';
320
- }
321
- /**
322
- * Configuration for nestjs-openapi.
323
- * Inspired by tsconfig.json and vite.config.ts patterns.
324
- *
325
- * @example
326
- * ```typescript
327
- * import { defineConfig } from 'nestjs-openapi';
328
- *
329
- * export default defineConfig({
330
- * output: 'src/openapi/openapi.generated.json',
331
- *
332
- * files: {
333
- * entry: 'src/app.module.ts',
334
- * dtoGlob: 'src/**\/*.dto.ts',
335
- * },
336
- *
337
- * openapi: {
338
- * info: {
339
- * title: 'My API',
340
- * version: '1.0.0',
341
- * },
342
- * },
343
- *
344
- * options: {
345
- * basePath: '/api',
346
- * extractValidation: true,
347
- * },
348
- * });
349
- * ```
350
- */
351
- interface Config {
352
- /**
353
- * Extend another config file. Paths are relative to this config file.
354
- * Extended config values are deeply merged, with this config taking precedence.
355
- * @example extends: './configs/base-openapi.config.ts'
356
- */
357
- readonly extends?: string;
358
- /**
359
- * Input file configuration.
360
- * All paths are relative to the config file location.
361
- */
362
- readonly files?: FilesConfig;
363
- /**
364
- * Output path for the generated OpenAPI specification.
365
- * Path is relative to the config file location.
366
- * @required
367
- */
368
- readonly output: string;
369
- /**
370
- * Output format for the specification.
371
- * @default "json"
372
- */
373
- readonly format?: OutputFormat;
374
- /**
375
- * OpenAPI specification metadata.
376
- * Maps directly to the OpenAPI spec structure.
377
- * @required
378
- */
379
- readonly openapi: OpenApiConfig;
380
- /**
381
- * Generation behavior options.
382
- */
383
- readonly options?: OptionsConfig;
384
- }
385
- /**
386
- * Options for the generate function to override config values.
387
- * Useful for CLI overrides.
388
- */
389
- interface GenerateOverrides {
390
- /**
391
- * Override the output format.
392
- * Takes precedence over config.format.
393
- */
394
- readonly format?: OutputFormat;
395
- /**
396
- * Enable debug mode for verbose logging and full stack traces.
397
- */
398
- readonly debug?: boolean;
399
- }
400
- /**
401
- * OpenAPI 3.0/3.1/3.2 specification schema object
402
- * Type can be a string or array of strings (for nullable in 3.1+)
403
- */
404
- interface OpenApiSchema {
405
- /** Schema type - string or array for 3.1+ nullable (e.g., ['string', 'null']) */
406
- readonly type?: string | readonly string[];
407
- readonly format?: string;
408
- readonly $ref?: string;
409
- readonly oneOf?: readonly OpenApiSchema[];
410
- readonly anyOf?: readonly OpenApiSchema[];
411
- readonly allOf?: readonly OpenApiSchema[];
412
- readonly items?: OpenApiSchema;
413
- readonly properties?: Record<string, OpenApiSchema>;
414
- readonly required?: readonly string[];
415
- readonly enum?: readonly unknown[];
416
- readonly description?: string;
417
- /** OpenAPI 3.0 only - use type: [T, 'null'] in 3.1+ instead */
418
- readonly nullable?: boolean;
419
- /** Examples array for 3.1+ (replaces single 'example' field) */
420
- readonly examples?: readonly unknown[];
421
- readonly minLength?: number;
422
- readonly maxLength?: number;
423
- readonly pattern?: string;
424
- readonly minimum?: number;
425
- readonly maximum?: number;
426
- readonly exclusiveMinimum?: number;
427
- readonly exclusiveMaximum?: number;
428
- readonly minItems?: number;
429
- readonly maxItems?: number;
430
- readonly default?: unknown;
431
- readonly additionalProperties?: boolean | OpenApiSchema;
432
- }
433
- /**
434
- * OpenAPI 3.0 parameter object
435
- */
436
- interface OpenApiParameter {
437
- readonly name: string;
438
- readonly in: 'path' | 'query' | 'header' | 'cookie';
439
- readonly description?: string;
440
- readonly required: boolean;
441
- readonly schema: OpenApiSchema;
442
- }
443
- /**
444
- * OpenAPI 3.0 request body object
445
- */
446
- interface OpenApiRequestBody {
447
- readonly description?: string;
448
- readonly required?: boolean;
449
- readonly content: Record<string, {
450
- readonly schema: OpenApiSchema;
451
- }>;
452
- }
453
- /**
454
- * OpenAPI 3.0 response object
455
- */
456
- interface OpenApiResponse {
457
- readonly description: string;
458
- readonly content?: Record<string, {
459
- readonly schema: OpenApiSchema;
460
- }>;
461
- }
462
- /**
463
- * OpenAPI 3.0 operation object
464
- */
465
- interface OpenApiOperation {
466
- readonly operationId: string;
467
- readonly summary?: string;
468
- readonly description?: string;
469
- readonly deprecated?: boolean;
470
- readonly tags?: readonly string[];
471
- readonly parameters?: readonly OpenApiParameter[];
472
- readonly requestBody?: OpenApiRequestBody;
473
- readonly responses: Record<string, OpenApiResponse>;
474
- /** Per-operation security requirements (overrides global security) */
475
- readonly security?: readonly SecurityRequirement[];
476
- }
477
- /**
478
- * OpenAPI 3.0 paths object
479
- * Maps path patterns to HTTP method operations
480
- */
481
- interface OpenApiPaths {
482
- readonly [path: string]: {
483
- readonly [method: string]: OpenApiOperation;
484
- };
485
- }
486
- /**
487
- * OpenAPI 3.0 OAuth2 flow object
488
- */
489
- interface OpenApiOAuth2Flow {
490
- readonly authorizationUrl?: string;
491
- readonly tokenUrl?: string;
492
- readonly refreshUrl?: string;
493
- readonly scopes: Record<string, string>;
494
- }
495
- /**
496
- * OpenAPI 3.0 OAuth2 flows object
497
- */
498
- interface OpenApiOAuth2Flows {
499
- readonly implicit?: OpenApiOAuth2Flow;
500
- readonly password?: OpenApiOAuth2Flow;
501
- readonly clientCredentials?: OpenApiOAuth2Flow;
502
- readonly authorizationCode?: OpenApiOAuth2Flow;
503
- }
504
- /**
505
- * OpenAPI 3.0 security scheme object
506
- */
507
- interface OpenApiSecurityScheme {
508
- readonly type: SecuritySchemeType;
509
- readonly description?: string;
510
- /** The name of the HTTP Authorization scheme (for type: 'http') */
511
- readonly scheme?: string;
512
- /** A hint for the format of the token (for type: 'http' with scheme: 'bearer') */
513
- readonly bearerFormat?: string;
514
- /** The location of the API key (for type: 'apiKey') */
515
- readonly in?: SecuritySchemeIn;
516
- /** The name of the header, query, or cookie parameter (for type: 'apiKey') */
517
- readonly name?: string;
518
- /** OAuth2 flows (for type: 'oauth2') */
519
- readonly flows?: OpenApiOAuth2Flows;
520
- /** OpenID Connect URL (for type: 'openIdConnect') */
521
- readonly openIdConnectUrl?: string;
522
- }
523
- /**
524
- * Webhook operation for OpenAPI 3.1+
525
- * Similar to regular operations but accessed via events rather than HTTP methods
526
- */
527
- interface OpenApiWebhookOperation {
528
- readonly post?: OpenApiOperation;
529
- readonly put?: OpenApiOperation;
530
- readonly patch?: OpenApiOperation;
531
- readonly delete?: OpenApiOperation;
532
- readonly get?: OpenApiOperation;
533
- }
534
- /**
535
- * Complete OpenAPI 3.0/3.1/3.2 specification
536
- */
537
- interface OpenApiSpec {
538
- readonly openapi: OpenApiVersion;
539
- readonly info: {
540
- readonly title: string;
541
- readonly version: string;
542
- readonly description?: string;
543
- readonly contact?: ContactConfig;
544
- readonly license?: LicenseConfig;
545
- };
546
- readonly servers?: readonly ServerConfig[];
547
- readonly tags?: readonly TagConfig[];
548
- readonly paths: OpenApiPaths;
549
- /** Webhooks for OpenAPI 3.1+ - event-driven operations */
550
- readonly webhooks?: Record<string, OpenApiWebhookOperation>;
551
- readonly components?: {
552
- readonly schemas?: Record<string, OpenApiSchema>;
553
- readonly securitySchemes?: Record<string, OpenApiSecurityScheme>;
554
- };
555
- /** Global security requirements */
556
- readonly security?: readonly SecurityRequirement[];
557
- }
558
-
559
- /**
560
- * OpenAPI spec validation utilities.
561
- *
562
- * Validates that generated specs don't have broken $ref references
563
- * or other common issues.
564
- */
565
-
566
- /**
567
- * A broken reference found during validation
568
- */
569
- interface BrokenRef {
570
- /** The $ref value that couldn't be resolved */
571
- readonly ref: string;
572
- /** The JSON path where this reference was found */
573
- readonly path: string;
574
- /** The schema name that's missing (extracted from $ref) */
575
- readonly missingSchema: string;
576
- }
577
- /**
578
- * Result of spec validation
579
- */
580
- interface ValidationResult {
581
- /** Whether the spec is valid (no broken refs) */
582
- readonly valid: boolean;
583
- /** Total number of schema refs found */
584
- readonly totalRefs: number;
585
- /** Number of broken refs */
586
- readonly brokenRefCount: number;
587
- /** Details of each broken ref */
588
- readonly brokenRefs: readonly BrokenRef[];
589
- /** Missing schema names grouped with their usage count */
590
- readonly missingSchemas: ReadonlyMap<string, number>;
591
- }
592
- /**
593
- * Validates an OpenAPI spec for broken $ref references.
594
- *
595
- * @param spec - The OpenAPI specification to validate
596
- * @returns Validation result with details about any broken refs
597
- *
598
- * @example
599
- * ```typescript
600
- * const result = validateSpec(spec);
601
- * if (!result.valid) {
602
- * console.error(`Found ${result.brokenRefCount} broken refs:`);
603
- * for (const [schema, count] of result.missingSchemas) {
604
- * console.error(` - ${schema} (${count} usages)`);
605
- * }
606
- * }
607
- * ```
608
- */
609
- declare function validateSpec(spec: OpenApiSpec): ValidationResult;
610
- /**
611
- * Categorizes broken refs by likely cause
612
- */
613
- interface BrokenRefCategories {
614
- /** Primitive types that shouldn't be refs (string, number, boolean) */
615
- readonly primitives: readonly string[];
616
- /** Union types (Type | null, void | Type) */
617
- readonly unionTypes: readonly string[];
618
- /** Query/Path parameter DTOs */
619
- readonly queryParams: readonly string[];
620
- /** Other missing schemas (likely from different glob patterns) */
621
- readonly other: readonly string[];
622
- }
623
- /**
624
- * Categorize broken refs to help diagnose the root cause.
625
- *
626
- * @param missingSchemas - Map of missing schema names to usage count
627
- * @returns Categorized broken refs
628
- */
629
- declare function categorizeBrokenRefs(missingSchemas: ReadonlyMap<string, number>): BrokenRefCategories;
630
- /**
631
- * Formats validation result as a human-readable string for CLI output.
632
- *
633
- * @param result - Validation result from validateSpec
634
- * @returns Formatted string describing the validation issues
635
- */
636
- declare function formatValidationResult(result: ValidationResult): string;
637
-
638
- /**
639
- * Promise-based entry point for generating OpenAPI specifications.
640
- *
641
- * This module provides a clean, Promise-based API that hides the internal
642
- * Effect-TS implementation from consumers.
643
- */
644
-
645
- interface GenerateResult {
646
- /** Path where the OpenAPI spec was written */
647
- readonly outputPath: string;
648
- /** Number of paths in the generated spec */
649
- readonly pathCount: number;
650
- /** Number of operations in the generated spec */
651
- readonly operationCount: number;
652
- /** Number of schemas in the generated spec */
653
- readonly schemaCount: number;
654
- /** Validation result checking for broken refs */
655
- readonly validation: ValidationResult;
656
- }
657
- /**
658
- * Generates an OpenAPI specification from a NestJS application.
659
- *
660
- * @param configPath - Path to the configuration file (openapi.config.ts)
661
- * @param options - Optional overrides for config values (e.g., format)
662
- * @returns Promise that resolves with generation result when complete
663
- *
664
- * @example
665
- * ```typescript
666
- * import { generate } from 'nestjs-openapi';
667
- *
668
- * await generate('apps/backend-api/openapi.config.ts');
669
- *
670
- * // Override format from CLI
671
- * await generate('apps/backend-api/openapi.config.ts', { format: 'yaml' });
672
- * ```
673
- */
674
- declare const generate: (configPath: string, overrides?: GenerateOverrides) => Promise<GenerateResult>;
675
-
676
- /**
677
- * Define configuration for OpenAPI generation.
678
- *
679
- * @example
680
- * ```typescript
681
- * export default defineConfig({
682
- * output: 'openapi.json',
683
- * files: { entry: 'src/app.module.ts' },
684
- * openapi: { info: { title: 'My API', version: '1.0.0' } },
685
- * });
686
- * ```
687
- */
688
- declare function defineConfig(config: Config): Config;
689
- declare const findConfigFile: (startDir?: string) => Effect.Effect<string, ConfigNotFoundError>;
690
- declare const loadConfigFromFile: (configPath: string) => Effect.Effect<typeof OpenApiGeneratorConfig.Type, ConfigError>;
691
- declare const loadConfig: (configPath?: string, cwd?: string) => Effect.Effect<typeof OpenApiGeneratorConfig.Type, ConfigError>;
692
- declare const resolveConfig: (config: typeof OpenApiGeneratorConfig.Type) => typeof ResolvedConfig.Type;
693
- declare const loadAndResolveConfig: (configPath?: string, cwd?: string) => Effect.Effect<typeof ResolvedConfig.Type, ConfigError>;
4
+ import { Effect, Option, Layer } from 'effect';
5
+ import { ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
694
6
 
695
7
  /**
696
8
  * NestJS Module for serving generated OpenAPI specifications at runtime.
@@ -783,6 +95,7 @@ declare function generateSwaggerUiHtml(title: string, jsonPath: string): string;
783
95
  /**
784
96
  * Load the OpenAPI spec file from disk
785
97
  */
98
+ declare const loadSpecFileEffect: (filePath: string) => Effect.Effect<OpenApiSpec, SpecFileNotFoundError | SpecFileReadError | SpecFileParseError, never>;
786
99
  declare function loadSpecFile(filePath: string): OpenApiSpec;
787
100
  /**
788
101
  * Resolve options with defaults
@@ -832,39 +145,6 @@ declare class OpenApiModule {
832
145
  static forRoot(options: OpenApiModuleOptions): DynamicModule;
833
146
  }
834
147
 
835
- interface ProjectContext {
836
- readonly project: Project;
837
- readonly entrySourceFile: SourceFile;
838
- readonly entryClass: ClassDeclaration;
839
- }
840
- interface ProjectOptions {
841
- readonly tsconfig: string;
842
- readonly entry: string;
843
- }
844
- declare const ProjectService_base: Context.TagClass<ProjectService, "ProjectService", {
845
- readonly context: ProjectContext;
846
- }>;
847
- /**
848
- * ProjectService is an infrastructure context holder.
849
- * Context.Tag is appropriate here as it holds externally-provided resources.
850
- */
851
- declare class ProjectService extends ProjectService_base {
852
- }
853
- declare const makeProjectContext: (options: ProjectOptions) => Effect.Effect<{
854
- project: Project;
855
- entrySourceFile: SourceFile;
856
- entryClass: ClassDeclaration;
857
- }, ProjectInitError | EntryNotFoundError, never>;
858
- declare const ProjectServiceLive: (options: ProjectOptions) => Layer.Layer<ProjectService, ProjectError>;
859
-
860
- interface ModuleWithControllers {
861
- readonly declaration: ClassDeclaration;
862
- readonly controllers: readonly ClassDeclaration[];
863
- }
864
- /** Iterative BFS to avoid stack overflow on deep module graphs */
865
- declare const getModules: (root: ClassDeclaration) => Effect.Effect<readonly ModuleWithControllers[], never, never>;
866
- declare const getAllControllers: (root: ClassDeclaration) => Effect.Effect<ClassDeclaration[], never, never>;
867
-
868
148
  declare const normalizePath: (path: string) => string;
869
149
  declare const getControllerPrefix: (controller: ClassDeclaration) => string;
870
150
  declare const getControllerName: (controller: ClassDeclaration) => string;
@@ -877,20 +157,159 @@ declare const getControllerTags: (controller: ClassDeclaration) => readonly stri
877
157
  declare const isHttpDecorator: (decorator: Decorator) => boolean;
878
158
  declare const getHttpDecorator: (method: MethodDeclaration) => Decorator | undefined;
879
159
 
880
- /** Configuration options for parameter extraction */
881
- interface ExtractParametersOptions {
882
- /** Query parameter handling options */
883
- readonly query?: {
884
- /** How to represent query DTOs: "inline" (default) or "ref" */
885
- readonly style?: 'inline' | 'ref';
160
+ declare const transformMethod: (methodInfo: MethodInfo) => OpenApiPaths;
161
+ declare const transformMethodEffect: (methodInfo: {
162
+ readonly security: readonly {
163
+ readonly scopes: readonly string[];
164
+ readonly schemeName: string;
165
+ }[];
166
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
167
+ readonly path: string;
168
+ readonly methodName: string;
169
+ readonly controllerName: string;
170
+ readonly controllerTags: readonly string[];
171
+ readonly returnType: {
172
+ readonly type: Option.Option<string>;
173
+ readonly inline: Option.Option<string>;
174
+ readonly container: Option.Option<"array">;
175
+ readonly filePath: Option.Option<string>;
176
+ };
177
+ readonly parameters: readonly {
178
+ readonly name: string;
179
+ readonly description: Option.Option<string>;
180
+ readonly location: "query" | "header" | "cookie" | "path" | "body";
181
+ readonly tsType: string;
182
+ readonly required: boolean;
183
+ }[];
184
+ readonly decorators: readonly string[];
185
+ readonly operation: {
186
+ readonly description: Option.Option<string>;
187
+ readonly summary: Option.Option<string>;
188
+ readonly operationId: Option.Option<string>;
189
+ readonly deprecated: Option.Option<boolean>;
190
+ };
191
+ readonly responses: readonly {
192
+ readonly description: Option.Option<string>;
193
+ readonly type: Option.Option<string>;
194
+ readonly statusCode: number;
195
+ readonly isArray: boolean;
196
+ }[];
197
+ readonly httpCode: Option.Option<number>;
198
+ readonly consumes: readonly string[];
199
+ readonly produces: readonly string[];
200
+ }) => Effect.Effect<OpenApiPaths, never, never>;
201
+ type MutableOpenApiPaths = {
202
+ [path: string]: {
203
+ [method: string]: OpenApiOperation;
204
+ };
205
+ };
206
+ declare const transformMethods: (methodInfos: readonly MethodInfo[]) => OpenApiPaths;
207
+ declare const transformMethodsEffect: (methodInfos: readonly {
208
+ readonly security: readonly {
209
+ readonly scopes: readonly string[];
210
+ readonly schemeName: string;
211
+ }[];
212
+ readonly httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "ALL";
213
+ readonly path: string;
214
+ readonly methodName: string;
215
+ readonly controllerName: string;
216
+ readonly controllerTags: readonly string[];
217
+ readonly returnType: {
218
+ readonly type: Option.Option<string>;
219
+ readonly inline: Option.Option<string>;
220
+ readonly container: Option.Option<"array">;
221
+ readonly filePath: Option.Option<string>;
222
+ };
223
+ readonly parameters: readonly {
224
+ readonly name: string;
225
+ readonly description: Option.Option<string>;
226
+ readonly location: "query" | "header" | "cookie" | "path" | "body";
227
+ readonly tsType: string;
228
+ readonly required: boolean;
229
+ }[];
230
+ readonly decorators: readonly string[];
231
+ readonly operation: {
232
+ readonly description: Option.Option<string>;
233
+ readonly summary: Option.Option<string>;
234
+ readonly operationId: Option.Option<string>;
235
+ readonly deprecated: Option.Option<boolean>;
886
236
  };
237
+ readonly responses: readonly {
238
+ readonly description: Option.Option<string>;
239
+ readonly type: Option.Option<string>;
240
+ readonly statusCode: number;
241
+ readonly isArray: boolean;
242
+ }[];
243
+ readonly httpCode: Option.Option<number>;
244
+ readonly consumes: readonly string[];
245
+ readonly produces: readonly string[];
246
+ }[]) => Effect.Effect<MutableOpenApiPaths, never, never>;
247
+
248
+ /**
249
+ * Schema Merger - Combines DTO schemas with path-referenced schemas
250
+ *
251
+ * This module merges generated DTO schemas into the final OpenAPI specification,
252
+ * ensuring all referenced schemas are included in components/schemas.
253
+ */
254
+
255
+ /**
256
+ * Result of schema merging
257
+ */
258
+ interface MergedResult {
259
+ /** The paths with updated $ref values */
260
+ readonly paths: OpenApiPaths$1;
261
+ /** All schemas to include in components/schemas */
262
+ readonly schemas: Record<string, OpenApiSchema>;
263
+ }
264
+ declare const mergeSchemas: (paths: OpenApiPaths$1, generatedSchemas: GeneratedSchemas) => MergedResult;
265
+ declare const mergeSchemasEffect: (paths: OpenApiPaths$1, generatedSchemas: GeneratedSchemas) => Effect.Effect<MergedResult, never, never>;
266
+ declare const mergeGeneratedSchemas: (...schemas: GeneratedSchemas[]) => GeneratedSchemas;
267
+ declare const mergeGeneratedSchemasEffect: (...args: GeneratedSchemas[]) => Effect.Effect<GeneratedSchemas, never, never>;
268
+ declare const filterSchemas: (schemas: GeneratedSchemas, include?: readonly string[], exclude?: readonly string[]) => GeneratedSchemas;
269
+ declare const filterSchemasEffect: (schemas: GeneratedSchemas, include?: readonly string[] | undefined, exclude?: readonly string[] | undefined) => Effect.Effect<GeneratedSchemas, never, never>;
270
+
271
+ /**
272
+ * Schema Name Normalizer
273
+ *
274
+ * Transforms ugly generic type names into clean, readable names.
275
+ * For example: `SelectRule<structure-1949804971-...>` → `SelectRule`
276
+ */
277
+
278
+ interface NormalizerOptions {
279
+ /**
280
+ * Whether to preserve the base name when stripping generics
281
+ * @default true
282
+ */
283
+ readonly preserveBaseName?: boolean;
284
+ /**
285
+ * Whether to deduplicate names with numeric suffixes
286
+ * @default false
287
+ */
288
+ readonly deduplicateSuffixes?: boolean;
289
+ /**
290
+ * Custom name mapping for specific types
291
+ */
292
+ readonly customNames?: Record<string, string>;
887
293
  }
888
- /** Returns None if the method has no HTTP decorator */
889
- declare const getMethodInfo: (controller: ClassDeclaration, method: MethodDeclaration, options?: ExtractParametersOptions) => Option.Option<MethodInfo>;
890
- declare const getControllerMethodInfos: (controller: ClassDeclaration, options?: ExtractParametersOptions) => readonly MethodInfo[];
294
+ declare const normalizeSchemas: (schemas: GeneratedSchemas, options?: NormalizerOptions) => GeneratedSchemas;
295
+ declare const normalizeSchemasEffect: (schemas: GeneratedSchemas, options?: NormalizerOptions | undefined) => Effect.Effect<GeneratedSchemas, never, never>;
296
+ declare const filterInternalSchemas: (schemas: GeneratedSchemas) => GeneratedSchemas;
297
+ declare const filterInternalSchemasEffect: (schemas: GeneratedSchemas) => Effect.Effect<GeneratedSchemas, never, never>;
298
+ /**
299
+ * Convert a string to PascalCase
300
+ * Examples:
301
+ * - `namespaceLabels` → `NamespaceLabels`
302
+ * - `k8sLabels` → `K8sLabels`
303
+ * - `NamespaceLabels` → `NamespaceLabels` (unchanged)
304
+ */
305
+ declare const toPascalCase: (str: string) => string;
306
+ declare const normalizeStructureRefs: (schemas: GeneratedSchemas) => GeneratedSchemas;
307
+ declare const normalizeStructureRefsEffect: (schemas: GeneratedSchemas) => Effect.Effect<GeneratedSchemas, never, never>;
891
308
 
892
- declare const transformMethod: (methodInfo: MethodInfo) => OpenApiPaths$1;
893
- declare const transformMethods: (methodInfos: readonly MethodInfo[]) => OpenApiPaths$1;
309
+ /**
310
+ * Shared service dependency graph for generation pipelines.
311
+ */
312
+ declare const generatorServicesLayer: Layer.Layer<ConfigService | ProjectService | ModuleTraversalService | MethodExtractionService | SchemaService | ValidationService | OutputService, never, never>;
894
313
 
895
314
  /** Handles aliased symbols (re-exports) */
896
315
  declare const resolveClassFromSymbol: (sym: Symbol) => Option.Option<ClassDeclaration>;
@@ -909,5 +328,5 @@ interface ModuleMetadata {
909
328
  }
910
329
  declare const getModuleMetadata: (mod: ClassDeclaration) => ModuleMetadata;
911
330
 
912
- export { ConfigError, ConfigNotFoundError, EntryNotFoundError, MethodInfo, OPENAPI_MODULE_OPTIONS, OPENAPI_SPEC, OpenApiGeneratorConfig, OpenApiModule, ProjectError, ProjectInitError, ProjectService, ProjectServiceLive, ResolvedConfig, categorizeBrokenRefs, defineConfig, findConfigFile, formatValidationResult, generate, generateSwaggerUiHtml, getAllControllers, getArrayInitializer, getControllerMethodInfos, getControllerName, getControllerPrefix, getControllerTags, getDecoratorName, getHttpDecorator, getHttpMethods, getMethodInfo, getModuleDecoratorArg, getModuleMetadata, getModules, getStringLiteralValue, getSymbolFromIdentifier, isHttpDecorator, isHttpMethod, isModuleClass, loadAndResolveConfig, loadConfig, loadConfigFromFile, loadSpecFile, makeProjectContext, normalizePath, resolveArrayOfClasses, resolveClassFromExpression, resolveClassFromSymbol, resolveConfig, resolveOptions, transformMethod, transformMethods, validateSpec };
913
- export type { BrokenRef, BrokenRefCategories, Config, ContactConfig, GenerateOverrides, GenerateResult, InfoConfig, LicenseConfig, ModuleMetadata, ModuleWithControllers, OpenApiModuleOptions, OpenApiOperation, OpenApiParameter, OpenApiPaths, OpenApiRequestBody, OpenApiResponse, OpenApiSchema, OpenApiSpec, OutputFormat, ProjectContext, ProjectOptions, ResolvedOpenApiModuleOptions, ServerConfig, SwaggerOptions, TagConfig, ValidationResult };
331
+ 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 };