ng-openapi 0.2.22 → 0.3.0

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.
Files changed (5) hide show
  1. package/README.md +41 -17
  2. package/cli.cjs +1199 -857
  3. package/index.d.ts +529 -83
  4. package/index.js +1265 -906
  5. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -2,52 +2,24 @@ import { Project, ScriptTarget, ModuleKind, MethodDeclaration, FunctionDeclarati
2
2
  import { HttpInterceptor } from '@angular/common/http';
3
3
  import { Info, ExternalDocs, Path, ParameterType, XML, BodyParameter, QueryParameter, Security, Tag } from 'swagger-schema-official';
4
4
 
5
- interface MethodGenerationContext {
6
- pathParams: Array<{
7
- name: string;
8
- in: string;
9
- }>;
10
- queryParams: Array<{
11
- name: string;
12
- in: string;
13
- }>;
14
- hasBody: boolean;
15
- isMultipart: boolean;
16
- isUrlEncoded: boolean;
17
- formDataFields: string[];
18
- urlEncodedFields: string[];
19
- responseType: "json" | "blob" | "arraybuffer" | "text";
20
- }
21
- interface TypeSchema {
22
- type?: string;
23
- format?: string;
24
- $ref?: string;
25
- items?: any;
26
- nullable?: boolean;
27
- enum?: Array<string | number>;
28
- [key: string]: any;
29
- }
30
- interface GetMethodGenerationContext {
31
- pathParams: Array<{
32
- name: string;
33
- in: string;
34
- }>;
35
- queryParams: Array<{
36
- name: string;
37
- in: string;
38
- }>;
39
- responseType: "json" | "blob" | "arraybuffer" | "text";
40
- }
41
-
5
+ /**
6
+ * An operation parameter. OpenAPI 3.x carries the type in `schema`;
7
+ * Swagger 2.0 puts `type`/`format` directly on the parameter — consumers
8
+ * must handle both (or use the normalized model, which precomputes them).
9
+ */
42
10
  interface Parameter {
43
11
  name: string;
44
12
  in: "query" | "path" | "header" | "cookie";
45
13
  required?: boolean;
46
- schema?: any;
14
+ schema?: SwaggerDefinition;
47
15
  type?: string;
48
16
  format?: string;
49
17
  description?: string;
50
18
  }
19
+ /**
20
+ * One operation of the spec, flattened to (path, method). Raw-ish view —
21
+ * generators consume its precomputed extension NormalizedOperation instead.
22
+ */
51
23
  interface PathInfo {
52
24
  path: string;
53
25
  method: string;
@@ -59,18 +31,29 @@ interface PathInfo {
59
31
  requestBody?: RequestBody;
60
32
  responses?: Record<string, SwaggerResponse>;
61
33
  }
34
+ /**
35
+ * Operation request body, keyed by content type — the OpenAPI 3.x shape.
36
+ * Swagger 2.0 `in: "body"` parameters are NOT yet lifted into this shape;
37
+ * 2.0 operations currently generate without a body parameter.
38
+ */
62
39
  interface RequestBody {
63
40
  required?: boolean;
64
41
  content?: Record<string, {
65
42
  schema?: SwaggerDefinition;
66
43
  }>;
67
44
  }
45
+ /**
46
+ * A single response entry, keyed by content type — the OpenAPI 3.x shape.
47
+ * A Swagger 2.0 response's direct `schema` is NOT yet mapped into `content`;
48
+ * 2.0 responses currently type as `any`.
49
+ */
68
50
  interface SwaggerResponse {
69
51
  description?: string;
70
52
  content?: Record<string, {
71
- schema?: any;
53
+ schema?: SwaggerDefinition;
72
54
  }>;
73
55
  }
56
+ /** OpenAPI 3.x security scheme (subset of the spec's fields). */
74
57
  interface OpenApiSecurityScheme {
75
58
  type?: "apiKey" | "http" | "oauth2" | "openIdConnect";
76
59
  description?: string;
@@ -78,15 +61,20 @@ interface OpenApiSecurityScheme {
78
61
  in?: "query" | "header" | "cookie";
79
62
  scheme?: string;
80
63
  bearerFormat?: string;
81
- flows?: Record<string, any>;
64
+ flows?: Record<string, unknown>;
82
65
  openIdConnectUrl?: string;
83
66
  }
67
+ /**
68
+ * A JSON-Schema-ish definition as it appears in the spec, shared by
69
+ * Swagger 2.0 and OpenAPI 3.x (3.0's `nullable` and 3.1's type arrays
70
+ * both flow through `type`/`nullable`). May contain unresolved `$ref`s.
71
+ */
84
72
  interface SwaggerDefinition {
85
73
  type?: ParameterType | undefined;
86
74
  format?: string | undefined;
87
75
  title?: string | undefined;
88
76
  description?: string | undefined;
89
- default?: any;
77
+ default?: unknown;
90
78
  multipleOf?: number | undefined;
91
79
  maximum?: number | undefined;
92
80
  exclusiveMaximum?: boolean | undefined;
@@ -100,7 +88,9 @@ interface SwaggerDefinition {
100
88
  uniqueItems?: boolean | undefined;
101
89
  maxProperties?: number | undefined;
102
90
  minProperties?: number | undefined;
103
- enum?: any[] | undefined;
91
+ enum?: Array<string | number> | undefined;
92
+ /** OpenAPI 3.1 (JSON Schema); normalizeSchema folds it into a single-value `enum`. */
93
+ const?: unknown;
104
94
  items?: SwaggerDefinition | SwaggerDefinition[] | undefined;
105
95
  $ref?: string | undefined;
106
96
  allOf?: SwaggerDefinition[] | undefined;
@@ -113,11 +103,16 @@ interface SwaggerDefinition {
113
103
  nullable?: boolean | undefined;
114
104
  xml?: XML | undefined;
115
105
  externalDocs?: ExternalDocs | undefined;
116
- example?: any;
106
+ example?: unknown;
117
107
  required?: string[] | undefined;
118
108
  oneOf?: SwaggerDefinition[];
119
109
  anyOf?: SwaggerDefinition[];
120
110
  }
111
+ /**
112
+ * The raw parsed spec document. Exactly one of `swagger` ("2.x") or
113
+ * `openapi` ("3.x") identifies the version; everything version-specific
114
+ * is resolved once by normalizeSpec.
115
+ */
121
116
  interface SwaggerSpec {
122
117
  openapi: string;
123
118
  swagger: string;
@@ -152,134 +147,539 @@ interface SwaggerSpec {
152
147
  securitySchemes?: Record<string, OpenApiSecurityScheme | Security>;
153
148
  };
154
149
  }
150
+ /**
151
+ * Shape of a JSON-encoded enum description consumed when
152
+ * `generateEnumBasedOnDescription` is enabled: the description holds
153
+ * `[{"Name":"First","Value":1}, …]` and supplies the member names.
154
+ */
155
155
  type EnumValueObject = {
156
156
  Name: string;
157
157
  Value: number;
158
158
  };
159
159
 
160
- declare class SwaggerParser {
161
- private readonly spec;
162
- private constructor();
163
- static create(swaggerPathOrUrl: string, config: GeneratorConfig): Promise<SwaggerParser>;
164
- private static loadContent;
165
- private static fetchUrlContent;
166
- private static parseSpecContent;
167
- private static detectFormat;
168
- getDefinitions(): Record<string, SwaggerDefinition>;
169
- getDefinition(name: string): SwaggerDefinition | undefined;
160
+ type ResponseKind = "json" | "blob" | "arraybuffer" | "text";
161
+ /**
162
+ * A spec operation with everything the generators need precomputed once at
163
+ * normalization time. Generators must not re-derive any of these fields or
164
+ * resolve $refs during emission — that is exactly the duplication this model
165
+ * exists to remove.
166
+ */
167
+ interface NormalizedOperation extends PathInfo {
168
+ /** parameters with in === "path" */
169
+ pathParams: Parameter[];
170
+ /** parameters with in === "query" */
171
+ queryParams: Parameter[];
172
+ hasBody: boolean;
173
+ isMultipart: boolean;
174
+ /** urlencoded body without a JSON alternative */
175
+ isUrlEncoded: boolean;
176
+ /** ref-resolved multipart body schema (set only when isMultipart) */
177
+ formDataSchema?: SwaggerDefinition;
178
+ /** field names of formDataSchema's properties */
179
+ formDataFields: string[];
180
+ /** ref-resolved urlencoded body schema (set only when isUrlEncoded) */
181
+ urlEncodedSchema?: SwaggerDefinition;
182
+ /** field names of urlEncodedSchema's properties */
183
+ urlEncodedFields: string[];
184
+ /** derived from the first success response (200/201/202/204/206) */
185
+ responseType: ResponseKind;
186
+ }
187
+
188
+ /** Detected spec flavor and its literal version string (e.g. openapi "3.0.3"). */
189
+ interface SpecVersion {
190
+ type: "swagger" | "openapi";
191
+ version: string;
192
+ }
193
+ /**
194
+ * Version-free view of a parsed spec: Swagger 2.0 vs OpenAPI 3.x differences
195
+ * are resolved once at normalization time. Generators consume this instead of
196
+ * touching the raw SwaggerSpec.
197
+ */
198
+ interface NormalizedSpec {
199
+ version: SpecVersion | null;
200
+ /** 2.0 `definitions` or 3.x `components.schemas`, whichever the spec has */
201
+ definitions: Record<string, SwaggerDefinition>;
202
+ operations: NormalizedOperation[];
203
+ /** Lookup for "#/definitions/X" and "#/components/schemas/X" style refs */
170
204
  resolveReference(ref: string): SwaggerDefinition | undefined;
171
- getAllDefinitionNames(): string[];
172
- getSpec(): SwaggerSpec;
173
- getPaths(): Record<string, any>;
174
- isValidSpec(): boolean;
175
- getSpecVersion(): {
176
- type: "swagger" | "openapi";
177
- version: string;
178
- } | null;
179
205
  }
180
206
 
181
207
  /**
182
- * Interface for generator class (both constructor and instance)
208
+ * Everything a plugin generator receives from the orchestrator.
209
+ *
210
+ * Plugins consume the version-free NormalizedSpec — never the raw spec or the
211
+ * SwaggerParser — and emit through the shared ts-morph Project so the
212
+ * orchestrator can track written files.
213
+ */
214
+ interface PluginGeneratorContext {
215
+ /** Version-free spec model; $refs resolved, per-operation fields precomputed. */
216
+ spec: NormalizedSpec;
217
+ /** Shared ts-morph project all generators emit through. */
218
+ project: Project;
219
+ /** Full user-facing config; plugins should read only the slice they need. */
220
+ config: GeneratorConfig;
221
+ /** Sink for non-fatal diagnostics — plugins must never log directly. */
222
+ onWarning?: (message: string) => void;
223
+ }
224
+ /**
225
+ * Constructor contract for plugin generator classes (what GeneratorConfig.plugins accepts).
183
226
  */
184
227
  interface IPluginGeneratorClass {
185
- /**
186
- * Constructor signature
187
- */
188
- new (parser: SwaggerParser, project: Project, config: GeneratorConfig): IPluginGenerator;
228
+ new (context: PluginGeneratorContext): IPluginGenerator;
189
229
  }
190
230
  /**
191
231
  * Interface for generator instances
192
232
  */
193
233
  interface IPluginGenerator {
194
234
  /**
195
- * Generate code files
235
+ * Generate code files under the given output root.
196
236
  */
197
237
  generate(outputRoot: string): Promise<void>;
198
238
  }
199
239
 
240
+ /**
241
+ * The user-facing configuration (config file or programmatic call).
242
+ * Validated at the boundary by validateGeneratorConfig, which throws
243
+ * ConfigValidationError listing every problem at once — see
244
+ * https://ng-openapi.dev for full option documentation.
245
+ */
200
246
  interface GeneratorConfig {
247
+ /** Path or http(s) URL of the OpenAPI 3.x / Swagger 2.x spec (.json/.yaml/.yml). */
201
248
  input: string;
249
+ /** Output directory; created if missing. */
202
250
  output: string;
251
+ /** Distinguishes tokens/providers when several clients coexist in one app. */
203
252
  clientName?: string;
253
+ /** Custom acceptance check run on the parsed spec; returning false aborts generation. */
204
254
  validateInput?: (spec: SwaggerSpec) => boolean;
205
255
  options: {
256
+ /** How date/date-time formats are typed in generated models. */
206
257
  dateType: "string" | "Date";
258
+ /** Emit TS enums or literal-union types for spec enums. */
207
259
  enumStyle: "enum" | "union";
208
260
  validation?: {
261
+ /** Adds a `parse` hook to RequestOptions for response validation. */
209
262
  response?: boolean;
210
263
  };
264
+ /** Set false to generate models only. Default: true. */
211
265
  generateServices?: boolean;
266
+ /** Read enum member names from JSON-encoded descriptions (see EnumValueObject). */
212
267
  generateEnumBasedOnDescription?: boolean;
268
+ /** Default headers added to every request when not already present. */
213
269
  customHeaders?: Record<string, string>;
270
+ /** Pin the Angular responseType per response content type. */
214
271
  responseTypeMapping?: {
215
272
  [contentType: string]: "json" | "blob" | "arraybuffer" | "text";
216
273
  };
274
+ /** Derive method names from operationIds; throws when an operation has none. */
217
275
  customizeMethodName?: (operationId: string) => string;
276
+ /** Collapse each method's parameters into a single request object. */
218
277
  useSingleRequestParameter?: boolean;
219
278
  };
279
+ /** Overrides for the ts-morph compiler settings used during generation. */
220
280
  compilerOptions?: {
221
281
  declaration?: boolean;
222
282
  target?: ScriptTarget;
223
283
  module?: ModuleKind;
224
284
  strict?: boolean;
225
285
  };
226
- plugins?: (new (...args: any) => IPluginGenerator)[];
286
+ /** Plugin generator classes, run after core generation (see PluginGeneratorContext). */
287
+ plugins?: IPluginGeneratorClass[];
288
+ }
289
+ /**
290
+ * Segregated views of GeneratorConfig.
291
+ * Generators declare the slice they actually consume; callers keep passing the
292
+ * full GeneratorConfig, which satisfies every view structurally. Only the
293
+ * user-facing boundary (CLI/orchestrator) and the plugin contract see the
294
+ * whole config.
295
+ */
296
+ /** What swagger→TypeScript type mapping needs (getTypeScriptType and friends). */
297
+ interface TypeMappingConfig {
298
+ options: {
299
+ dateType: "string" | "Date";
300
+ };
227
301
  }
302
+ /** Options consumed by model/interface generation (TypeGenerator). */
303
+ interface TypeGenOptions {
304
+ options: {
305
+ dateType: "string" | "Date";
306
+ enumStyle: "enum" | "union";
307
+ generateEnumBasedOnDescription?: boolean;
308
+ validation?: {
309
+ response?: boolean;
310
+ };
311
+ };
312
+ }
313
+ /** Options consumed by the service/resource method-generation chain. */
314
+ interface MethodGenOptions {
315
+ options: {
316
+ dateType: "string" | "Date";
317
+ validation?: {
318
+ response?: boolean;
319
+ };
320
+ customHeaders?: Record<string, string>;
321
+ customizeMethodName?: (operationId: string) => string;
322
+ useSingleRequestParameter?: boolean;
323
+ };
324
+ }
325
+ /** Per-client runtime configuration consumed by the generated provider functions. */
228
326
  interface NgOpenapiClientConfig {
327
+ /** Unique identifier for this client (matches GeneratorConfig.clientName). */
229
328
  clientName: string;
230
329
  basePath: string;
231
330
  enableDateTransform?: boolean;
232
331
  interceptors?: (new (...args: HttpInterceptor[]) => HttpInterceptor)[];
233
332
  }
234
333
 
334
+ /**
335
+ * Per-operation facts a method generator needs while emitting a body.
336
+ * The normalizer precomputes all of these onto NormalizedOperation —
337
+ * this shape survives for consumers that carry them separately.
338
+ */
339
+ interface MethodGenerationContext {
340
+ pathParams: Array<{
341
+ name: string;
342
+ in: string;
343
+ }>;
344
+ queryParams: Array<{
345
+ name: string;
346
+ in: string;
347
+ }>;
348
+ hasBody: boolean;
349
+ isMultipart: boolean;
350
+ isUrlEncoded: boolean;
351
+ formDataFields: string[];
352
+ urlEncodedFields: string[];
353
+ responseType: "json" | "blob" | "arraybuffer" | "text";
354
+ }
355
+ /**
356
+ * Loose schema shape accepted by getTypeScriptType at boundaries where a
357
+ * fully-typed SwaggerDefinition isn't available (e.g. Swagger 2.0 parameters
358
+ * carrying type/format directly). The index signature admits raw spec JSON.
359
+ */
360
+ interface TypeSchema {
361
+ type?: string;
362
+ format?: string;
363
+ $ref?: string;
364
+ items?: TypeSchema | TypeSchema[];
365
+ nullable?: boolean;
366
+ enum?: Array<string | number>;
367
+ [key: string]: unknown;
368
+ }
369
+ /** MethodGenerationContext subset that GET-only generation (http-resource) needs. */
370
+ interface GetMethodGenerationContext {
371
+ pathParams: Array<{
372
+ name: string;
373
+ in: string;
374
+ }>;
375
+ queryParams: Array<{
376
+ name: string;
377
+ in: string;
378
+ }>;
379
+ responseType: "json" | "blob" | "arraybuffer" | "text";
380
+ }
381
+
382
+ /**
383
+ * Typed access to a parsed OpenAPI/Swagger spec.
384
+ * Loading (fs/http) lives in spec-loader.ts; format detection and parsing in
385
+ * spec-format.ts — this class is a façade over both plus spec accessors.
386
+ */
387
+ declare class SwaggerParser {
388
+ private readonly spec;
389
+ private normalized?;
390
+ private constructor();
391
+ /**
392
+ * Loads, parses and wraps a spec.
393
+ *
394
+ * @throws SpecLoadError when the file/URL cannot be read.
395
+ * @throws SpecParseError when the content cannot be parsed or the
396
+ * config's `validateInput` hook rejects the spec.
397
+ */
398
+ static create(swaggerPathOrUrl: string, config: GeneratorConfig): Promise<SwaggerParser>;
399
+ /**
400
+ * The version-free model generators consume. Computed once and cached —
401
+ * all generators share the same NormalizedOperation instances, so they
402
+ * can be used as Map keys across generators.
403
+ */
404
+ getNormalizedSpec(): NormalizedSpec;
405
+ /** Definition map regardless of version: 2.0 `definitions` or 3.x `components.schemas`. */
406
+ getDefinitions(): Record<string, SwaggerDefinition>;
407
+ /** One definition by bare name, or undefined when the spec has none by that name. */
408
+ getDefinition(name: string): SwaggerDefinition | undefined;
409
+ /** Resolves "#/definitions/X" / "#/components/schemas/X" style refs by their last segment. */
410
+ resolveReference(ref: string): SwaggerDefinition | undefined;
411
+ getAllDefinitionNames(): string[];
412
+ /** The raw parsed spec — prefer getNormalizedSpec() unless raw access is the point. */
413
+ getSpec(): SwaggerSpec;
414
+ getPaths(): SwaggerSpec["paths"];
415
+ /** Whether the spec declares a supported version (Swagger 2.x or OpenAPI 3.x). */
416
+ isValidSpec(): boolean;
417
+ /** Detected flavor + literal version string, or null when neither field is present. */
418
+ getSpecVersion(): {
419
+ type: "swagger" | "openapi";
420
+ version: string;
421
+ } | null;
422
+ }
423
+
424
+ /**
425
+ * Normalizes a parsed spec into the version-free model the generators consume.
426
+ * Everything here used to be re-derived per generator (service-method body,
427
+ * http-resource body, overloads) — computing it once keeps the derivations
428
+ * identical by construction.
429
+ */
430
+ declare function normalizeSpec(spec: SwaggerSpec): NormalizedSpec;
431
+ /**
432
+ * Normalizes the JSON-Schema constructs OpenAPI 3.1 introduced so generators
433
+ * never see them:
434
+ *
435
+ * - type arrays: `"null"` members fold into `nullable: true`, and a single
436
+ * remaining type collapses to a plain string type — so `format`, `enum` and
437
+ * friends keep working on nullable 3.1 schemas.
438
+ * - `const` becomes a single-value `enum`.
439
+ *
440
+ * Returns a deep copy; the raw spec is never mutated. Schemas without 3.1
441
+ * constructs come back semantically identical.
442
+ */
443
+ declare function normalizeSchema(schema: SwaggerDefinition): SwaggerDefinition;
444
+
445
+ /**
446
+ * Typed, user-facing errors of the spec pipeline.
447
+ *
448
+ * Hosts (CLI, programmatic callers, tests) branch on the error class — never
449
+ * on message text, which is presentation and not part of the API contract.
450
+ */
451
+ /** Base class of every error ng-openapi raises deliberately. */
452
+ declare class NgOpenApiError extends Error {
453
+ /** The underlying error that caused this one, when there is one. */
454
+ readonly cause?: unknown;
455
+ constructor(message: string, cause?: unknown);
456
+ }
457
+ /**
458
+ * The spec input could not be read at all: missing/unreadable file,
459
+ * unsupported file extension, HTTP failure, timeout, or empty response.
460
+ * `source` is the offending path or URL — the CLI uses it to decide
461
+ * which hints to print.
462
+ */
463
+ declare class SpecLoadError extends NgOpenApiError {
464
+ /** The file path or URL that failed to load. */
465
+ readonly source: string;
466
+ constructor(message: string, source: string, cause?: unknown);
467
+ }
468
+ /**
469
+ * The spec content was read but could not be used: malformed JSON/YAML,
470
+ * undeterminable format, an unsupported spec version, or a spec rejected
471
+ * by the user's `validateInput` hook.
472
+ */
473
+ declare class SpecParseError extends NgOpenApiError {
474
+ /** The file path or URL the content came from, when known. */
475
+ readonly source?: string;
476
+ constructor(message: string, source?: string, cause?: unknown);
477
+ }
478
+
479
+ interface HeadersEmitOptions {
480
+ /** Identifier of the per-request options parameter in the generated method ("options", "requestOptions", …). */
481
+ optionsExpression: string;
482
+ /** Default headers from GeneratorConfig, added when not already present on the request. */
483
+ customHeaders?: Record<string, string>;
484
+ /** Content-Type rules derived from the operation's body; omit to skip (http-resource is GET-only). */
485
+ contentType?: {
486
+ isMultipart: boolean;
487
+ isUrlEncoded: boolean;
488
+ hasBody: boolean;
489
+ };
490
+ }
491
+ /**
492
+ * Emits the `headers` initialization block: normalize the caller-supplied
493
+ * headers into HttpHeaders, apply configured default headers, then apply
494
+ * Content-Type rules.
495
+ */
496
+ declare function emitHeaders(options: HeadersEmitOptions): string;
497
+ /**
498
+ * Merges configured default headers into caller headers that may be an
499
+ * HttpHeaders instance or a plain record (http-resource's request options).
500
+ * Cast-free: the plain record is never funneled through the HttpHeaders
501
+ * constructor, whose accepted value types are narrower than
502
+ * HttpResourceRequest's.
503
+ */
504
+ declare function emitDefaultHeadersMerge(optionsExpression: string, customHeaders: Record<string, string>): string;
505
+
506
+ /**
507
+ * Emits the `HttpParams` accumulation block for the core service method body.
508
+ * Returns "" when the operation has no query parameters.
509
+ */
510
+ declare function emitQueryParams(queryParams: Parameter[]): string;
511
+ /**
512
+ * Signal-aware variant for the http-resource plugin: each parameter may be a
513
+ * signal, so its value is read once before the null check.
514
+ */
515
+ declare function emitSignalAwareQueryParams(queryParams: Parameter[]): string;
516
+
517
+ /**
518
+ * Returns the request-options entry pinning a non-JSON response type, or ""
519
+ * for JSON (Angular's default). The entry is cast-free: it must be emitted
520
+ * into a contextually typed position (an options literal inlined into the
521
+ * `request()` call) so the literal keeps its narrow type.
522
+ */
523
+ declare function emitResponseTypeOption(responseType: ResponseKind): string;
524
+ /**
525
+ * Joins requestOptions entries, dropping empties and entries referencing
526
+ * undefined values, with the indentation both method bodies use.
527
+ */
528
+ declare function joinRequestOptionEntries(entries: string[]): string;
529
+
530
+ /** Identity read: the parameter identifier is a plain value. */
531
+ declare function plainParamValue(identifier: string): string;
532
+ /** Signal-aware read used by the http-resource plugin: the value may be a signal → call it. */
533
+ declare function signalAwareParamValue(identifier: string): string;
534
+ /**
535
+ * Builds the request-URL template literal, substituting `{param}` placeholders
536
+ * with the (camelCased) method parameter identifiers.
537
+ */
538
+ declare function emitUrlExpression(path: string, pathParams: Parameter[], paramValue?: (identifier: string) => string): string;
539
+ /** `const url = …;` statement used by the core service method body. */
540
+ declare function emitUrlConstruction(path: string, pathParams: Parameter[]): string;
541
+
542
+ /**
543
+ * Converts a string to camelCase. Dots, dashes, underscores and whitespace are
544
+ * treated as word separators and removed (`"pet_id"` → `"petId"`,
545
+ * `"filter.name"` → `"filterName"`).
546
+ */
235
547
  declare function camelCase(str: string): string;
548
+ /** Converts a string to kebab-case (`"PetStore"` → `"pet-store"`). */
236
549
  declare function kebabCase(str: string): string;
550
+ /**
551
+ * Converts a string to PascalCase. Dots, dashes, underscores and whitespace
552
+ * are treated as word separators and removed (`"pet_store"` → `"PetStore"`).
553
+ */
237
554
  declare function pascalCase(str: string): string;
555
+ /** Converts a string to SCREAMING_SNAKE_CASE (`"PetStore"` → `"PET_STORE"`) — used for token names. */
238
556
  declare function screamingSnakeCase(str: string): string;
557
+ /**
558
+ * PascalCase variant safe for generated type/enum identifiers: every
559
+ * non-alphanumeric character is a separator, and a leading digit is
560
+ * prefixed with `_` so the result is always a valid TS identifier.
561
+ */
239
562
  declare function pascalCaseForEnums(str: string): string;
240
563
 
241
564
  /**
242
565
  * Convert OpenAPI/Swagger types to TypeScript types
243
- * @param schemaOrType - Either a schema object or a type string
566
+ * @param schemaOrType - Either a schema object (loose TypeSchema or a parsed SwaggerDefinition) or a type string
244
567
  * @param config - generator configuration
245
568
  * @param formatOrNullable - Either format string (if first param is string) or nullable boolean
246
569
  * @param isNullable - Nullable boolean (only used if first param is string)
247
570
  * @param context - Whether this is for type generation or service generation
248
571
  */
249
- declare function getTypeScriptType(schemaOrType: TypeSchema | string | undefined, config: GeneratorConfig, formatOrNullable?: string | boolean, isNullable?: boolean, context?: "type" | "service"): string;
572
+ declare function getTypeScriptType(schemaOrType: TypeSchema | SwaggerDefinition | string | undefined, config: TypeMappingConfig, formatOrNullable?: string | boolean, isNullable?: boolean, context?: "type" | "service"): string;
573
+ /** Appends `| null` to a type expression when the schema is nullable. */
250
574
  declare function nullableType(type: string, isNullable?: boolean): string;
575
+ /** Escapes backslashes and single quotes for embedding in a single-quoted generated literal. */
251
576
  declare function escapeString(str: string): string;
252
577
 
253
- type placeHolder = {};
578
+ /** The content types the generators special-case when emitting method bodies. */
579
+ declare const CONTENT_TYPES: {
580
+ MULTIPART: string;
581
+ FORM_URLENCODED: string;
582
+ JSON: string;
583
+ };
254
584
 
585
+ /**
586
+ * Names of the injection tokens emitted into each client's tokens/index.ts.
587
+ * The client name is normalized to SCREAMING_SNAKE (non-alphanumerics → `_`)
588
+ * and suffixed, so multiple clients can coexist in one application
589
+ * (`"PetsApi"` → `BASE_PATH_PETSAPI`); the default client uses `_DEFAULT`.
590
+ */
591
+ /** Token identifying which client a request belongs to (read by interceptors). */
255
592
  declare function getClientContextTokenName(clientName?: string): string;
593
+ /** Token providing the API base path for the client. */
256
594
  declare function getBasePathTokenName(clientName?: string): string;
595
+ /** Token carrying the client's interceptor chain. */
257
596
  declare function getInterceptorsTokenName(clientName?: string): string;
258
597
 
598
+ /** Whether two or more declarations share a name — generation aborts on colliding method names. */
259
599
  declare function hasDuplicateFunctionNames<T extends MethodDeclaration | FunctionDeclaration>(arr: T[]): boolean;
260
600
 
601
+ /**
602
+ * Flattens the spec's `paths` object into one PathInfo per (path, method)
603
+ * pair, merging path-level parameters into each operation. Supports both
604
+ * Swagger 2.0 and OpenAPI 3.x path items; methods outside the given list
605
+ * (and vendor extensions) are ignored.
606
+ */
261
607
  declare function extractPaths(swaggerPaths?: {
262
608
  [p: string]: Path;
263
609
  }, methods?: string[]): PathInfo[];
264
610
 
611
+ /**
612
+ * Angular `responseType` for a response: inspects every content type the
613
+ * response declares and picks the highest-priority match (JSON-like content
614
+ * beats text beats binary). `responseTypeMapping` lets the user config pin a
615
+ * responseType per content type; empty content defaults to "json".
616
+ */
265
617
  declare function getResponseTypeFromResponse(response: SwaggerResponse, responseTypeMapping?: {
266
618
  [p: string]: "json" | "blob" | "arraybuffer" | "text";
267
619
  }): "json" | "blob" | "arraybuffer" | "text";
268
- declare function isPrimitiveType(schema: any): boolean;
620
+ /**
621
+ * Whether a schema resolves to a bare primitive (string/number/integer/
622
+ * boolean). Arrays, objects, $refs and compositions all count as complex.
623
+ */
624
+ declare function isPrimitiveType(schema: SwaggerDefinition | undefined): boolean;
625
+ /**
626
+ * Maps a MIME type (parameters like charset stripped) to the Angular
627
+ * `responseType` used when fetching it; unknown types are assumed binary.
628
+ */
269
629
  declare function inferResponseTypeFromContentType(contentType: string): "json" | "blob" | "arraybuffer" | "text";
270
- declare function getResponseType(response: SwaggerResponse, config: GeneratorConfig): string;
630
+ /**
631
+ * TS type of a response body for generated signatures: schema-derived when
632
+ * the response declares one, otherwise Blob/ArrayBuffer/string per the
633
+ * detected responseType ("any" for schema-less JSON).
634
+ */
635
+ declare function getResponseType(response: SwaggerResponse, config: TypeMappingConfig): string;
271
636
 
272
- declare function getRequestBodyType(requestBody: RequestBody, config: GeneratorConfig): string;
637
+ /**
638
+ * TS type of an operation's JSON request body; `"any"` when the body has no
639
+ * JSON content or no schema. Multipart/urlencoded bodies are handled
640
+ * separately by the method-body emission.
641
+ */
642
+ declare function getRequestBodyType(requestBody: RequestBody, config: TypeMappingConfig): string;
273
643
 
644
+ /**
645
+ * Whether a rendered TS type expression refers to a generated model interface
646
+ * (as opposed to a primitive, `File`, an array or an inline shape) — used to
647
+ * decide parameter naming in generated methods.
648
+ */
274
649
  declare function isDataTypeInterface(type: string): boolean;
275
650
 
651
+ /**
652
+ * Type-parameter expression for request-validation overloads: the request
653
+ * body's interface type (with `| undefined` when optional), or "" when the
654
+ * method has no interface-typed body parameter.
655
+ */
276
656
  declare function generateParseRequestTypeParams(params: OptionalKind<ParameterDeclarationStructure>[]): string;
277
657
 
278
- declare const CONTENT_TYPES: {
279
- MULTIPART: string;
280
- FORM_URLENCODED: string;
281
- JSON: string;
282
- };
658
+ /**
659
+ * Determines if input is a URL
660
+ */
661
+ declare function isUrl(input: string): boolean;
662
+
663
+ /**
664
+ * Identity helper for config files: full type inference and IDE autocomplete
665
+ * without a manual type annotation.
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * // openapi.config.ts
670
+ * import { defineConfig } from "ng-openapi";
671
+ *
672
+ * export default defineConfig({
673
+ * input: "./swagger.json",
674
+ * output: "./src/api",
675
+ * options: { dateType: "Date", enumStyle: "enum" },
676
+ * });
677
+ * ```
678
+ *
679
+ * Purely compile-time sugar — runtime validation still happens in
680
+ * validateGeneratorConfig at the generation boundary.
681
+ */
682
+ declare function defineConfig(config: GeneratorConfig): GeneratorConfig;
283
683
 
284
684
  declare const TYPE_GENERATOR_HEADER_COMMENT: string;
285
685
  declare const SERVICE_INDEX_GENERATOR_HEADER_COMMENT: string;
@@ -293,12 +693,58 @@ declare const ZOD_PLUGIN_GENERATOR_HEADER_COMMENT: (validatorName: string) => st
293
693
  declare const ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT: string;
294
694
 
295
695
  /**
296
- * Validates input (file or URL)
696
+ * Progress/diagnostics contract between the pure orchestrator and whatever
697
+ * hosts it (CLI, tests, programmatic callers). The orchestrator never logs;
698
+ * presentation lives entirely in the host's Reporter implementation.
699
+ */
700
+ type GenerationPhase = "processing-spec" | "types-generated" | "services-generated" | "plugins-generated";
701
+ interface Reporter {
702
+ /** Called when a generation phase completes (or, for "processing-spec", starts). */
703
+ onPhase?(phase: GenerationPhase): void;
704
+ /** Called for non-fatal problems; the same messages end up on GenerationResult.warnings. */
705
+ onWarning?(message: string): void;
706
+ }
707
+ /** Structured outcome of generateFromConfig — inspectable, no side channel. */
708
+ interface GenerationResult {
709
+ /** clientName from the config, when set. */
710
+ client?: string;
711
+ /** Absolute paths of every file the generation wrote. */
712
+ filesWritten: string[];
713
+ /** Non-fatal problems encountered during generation. */
714
+ warnings: string[];
715
+ durationMs: number;
716
+ }
717
+
718
+ /**
719
+ * Validates input (file or URL).
720
+ *
721
+ * @throws SpecLoadError when a local input file is missing or has an
722
+ * unsupported extension. URLs are validated by the loader when fetched.
297
723
  */
298
724
  declare function validateInput(inputPath: string): void;
299
725
  /**
300
- * Generates Angular services and types from a configuration object
726
+ * Generates Angular services and types from a configuration object.
727
+ *
728
+ * Pure orchestration: no logging, no process concerns. Progress and warnings
729
+ * are surfaced through the optional Reporter and the returned
730
+ * GenerationResult; presentation (emojis, hints, exit codes) is the CLI's job.
731
+ *
732
+ * @throws ConfigValidationError when the config is structurally invalid.
733
+ * @throws SpecLoadError when the input file/URL cannot be read.
734
+ * @throws SpecParseError when the spec cannot be parsed, has an unsupported
735
+ * version, or is rejected by the config's `validateInput` hook.
301
736
  */
302
- declare function generateFromConfig(config: GeneratorConfig): Promise<void>;
737
+ declare function generateFromConfig(config: GeneratorConfig, reporter?: Reporter): Promise<GenerationResult>;
738
+
739
+ /**
740
+ * Thrown when the user-supplied config is structurally invalid. Collects every
741
+ * issue instead of failing on the first one, so a config file can be fixed in
742
+ * one pass.
743
+ */
744
+ declare class ConfigValidationError extends Error {
745
+ readonly issues: string[];
746
+ constructor(issues: string[]);
747
+ }
748
+ declare function validateGeneratorConfig(config: unknown): asserts config is GeneratorConfig;
303
749
 
304
- export { BASE_INTERCEPTOR_HEADER_COMMENT, CONTENT_TYPES, type EnumValueObject, type GeneratorConfig, type GetMethodGenerationContext, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT, type IPluginGenerator, type IPluginGeneratorClass, MAIN_INDEX_GENERATOR_HEADER_COMMENT, type MethodGenerationContext, type NgOpenapiClientConfig, type OpenApiSecurityScheme, PROVIDER_GENERATOR_HEADER_COMMENT, type Parameter, type PathInfo, REQUEST_PARAMS_GENERATOR_HEADER_COMMENT, type RequestBody, SERVICE_GENERATOR_HEADER_COMMENT, SERVICE_INDEX_GENERATOR_HEADER_COMMENT, type SwaggerDefinition, SwaggerParser, type SwaggerResponse, type SwaggerSpec, TYPE_GENERATOR_HEADER_COMMENT, type TypeSchema, ZOD_PLUGIN_GENERATOR_HEADER_COMMENT, ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT, camelCase, escapeString, extractPaths, generateFromConfig, generateParseRequestTypeParams, getBasePathTokenName, getClientContextTokenName, getInterceptorsTokenName, getRequestBodyType, getResponseType, getResponseTypeFromResponse, getTypeScriptType, hasDuplicateFunctionNames, inferResponseTypeFromContentType, isDataTypeInterface, isPrimitiveType, kebabCase, nullableType, pascalCase, pascalCaseForEnums, type placeHolder, screamingSnakeCase, validateInput };
750
+ export { BASE_INTERCEPTOR_HEADER_COMMENT, CONTENT_TYPES, ConfigValidationError, type EnumValueObject, type GenerationPhase, type GenerationResult, type GeneratorConfig, type GetMethodGenerationContext, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT, type HeadersEmitOptions, type IPluginGenerator, type IPluginGeneratorClass, MAIN_INDEX_GENERATOR_HEADER_COMMENT, type MethodGenOptions, type MethodGenerationContext, NgOpenApiError, type NgOpenapiClientConfig, type NormalizedOperation, type NormalizedSpec, type OpenApiSecurityScheme, PROVIDER_GENERATOR_HEADER_COMMENT, type Parameter, type PathInfo, type PluginGeneratorContext, REQUEST_PARAMS_GENERATOR_HEADER_COMMENT, type Reporter, type RequestBody, type ResponseKind, SERVICE_GENERATOR_HEADER_COMMENT, SERVICE_INDEX_GENERATOR_HEADER_COMMENT, SpecLoadError, SpecParseError, type SpecVersion, type SwaggerDefinition, SwaggerParser, type SwaggerResponse, type SwaggerSpec, TYPE_GENERATOR_HEADER_COMMENT, type TypeGenOptions, type TypeMappingConfig, type TypeSchema, ZOD_PLUGIN_GENERATOR_HEADER_COMMENT, ZOD_PLUGIN_INDEX_GENERATOR_HEADER_COMMENT, camelCase, defineConfig, emitDefaultHeadersMerge, emitHeaders, emitQueryParams, emitResponseTypeOption, emitSignalAwareQueryParams, emitUrlConstruction, emitUrlExpression, escapeString, extractPaths, generateFromConfig, generateParseRequestTypeParams, getBasePathTokenName, getClientContextTokenName, getInterceptorsTokenName, getRequestBodyType, getResponseType, getResponseTypeFromResponse, getTypeScriptType, hasDuplicateFunctionNames, inferResponseTypeFromContentType, isDataTypeInterface, isPrimitiveType, isUrl, joinRequestOptionEntries, kebabCase, normalizeSchema, normalizeSpec, nullableType, pascalCase, pascalCaseForEnums, plainParamValue, screamingSnakeCase, signalAwareParamValue, validateGeneratorConfig, validateInput };