@effect/openapi-generator 4.0.0-beta.66 → 4.0.0-beta.68
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/HttpApiTransformer.d.ts +31 -0
- package/dist/HttpApiTransformer.d.ts.map +1 -1
- package/dist/HttpApiTransformer.js +20 -0
- package/dist/HttpApiTransformer.js.map +1 -1
- package/dist/JsonSchemaGenerator.d.ts +10 -0
- package/dist/JsonSchemaGenerator.d.ts.map +1 -1
- package/dist/JsonSchemaGenerator.js +30 -0
- package/dist/JsonSchemaGenerator.js.map +1 -1
- package/dist/OpenApiGenerator.d.ts +62 -0
- package/dist/OpenApiGenerator.d.ts.map +1 -1
- package/dist/OpenApiGenerator.js +37 -0
- package/dist/OpenApiGenerator.js.map +1 -1
- package/dist/OpenApiPatch.d.ts +27 -20
- package/dist/OpenApiPatch.d.ts.map +1 -1
- package/dist/OpenApiPatch.js +26 -19
- package/dist/OpenApiPatch.js.map +1 -1
- package/dist/OpenApiTransformer.d.ts +63 -0
- package/dist/OpenApiTransformer.d.ts.map +1 -1
- package/dist/OpenApiTransformer.js +63 -0
- package/dist/OpenApiTransformer.js.map +1 -1
- package/dist/ParsedOperation.d.ts +90 -0
- package/dist/ParsedOperation.d.ts.map +1 -1
- package/dist/ParsedOperation.js +6 -0
- package/dist/ParsedOperation.js.map +1 -1
- package/dist/Utils.d.ts +43 -0
- package/dist/Utils.d.ts.map +1 -1
- package/dist/Utils.js +53 -0
- package/dist/Utils.js.map +1 -1
- package/dist/main.d.ts +10 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -0
- package/dist/main.js.map +1 -1
- package/package.json +5 -5
- package/src/HttpApiTransformer.ts +31 -0
- package/src/JsonSchemaGenerator.ts +30 -0
- package/src/OpenApiGenerator.ts +62 -0
- package/src/OpenApiPatch.ts +27 -20
- package/src/OpenApiTransformer.ts +63 -0
- package/src/ParsedOperation.ts +90 -0
- package/src/Utils.ts +53 -0
- package/src/main.ts +20 -0
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate TypeScript source for JSON Schema declarations extracted from
|
|
3
|
+
* OpenAPI documents.
|
|
4
|
+
*
|
|
5
|
+
* This module is the schema-rendering stage of the OpenAPI generator. Callers
|
|
6
|
+
* register named OpenAPI 3.0 or 3.1 schemas, provide the reusable component
|
|
7
|
+
* definitions for the document, and receive source text containing exported
|
|
8
|
+
* TypeScript aliases plus Effect Schema runtime values. The generator first
|
|
9
|
+
* normalizes OpenAPI-specific schema shapes into Effect's JSON Schema model,
|
|
10
|
+
* then delegates recursive analysis and runtime expression construction to
|
|
11
|
+
* `SchemaRepresentation`.
|
|
12
|
+
*
|
|
13
|
+
* The renderer keeps the emitted module usable for both human maintainers and
|
|
14
|
+
* automated code-generation consumers by grouping recursive declarations,
|
|
15
|
+
* reusable references, and locally registered schemas. It also contains the
|
|
16
|
+
* HttpApi-specific multipart file substitutions that map generated schemas to
|
|
17
|
+
* Effect's multipart runtime types.
|
|
18
|
+
*
|
|
19
|
+
* @since 4.0.0
|
|
20
|
+
*/
|
|
1
21
|
import * as Arr from "effect/Array"
|
|
2
22
|
import * as JsonSchema from "effect/JsonSchema"
|
|
3
23
|
import * as Rec from "effect/Record"
|
|
@@ -16,6 +36,16 @@ interface GenerateHttpApiOptions extends GenerateOptions {
|
|
|
16
36
|
} | undefined
|
|
17
37
|
}
|
|
18
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Create a stateful JSON Schema code generator for OpenAPI-derived schemas.
|
|
41
|
+
*
|
|
42
|
+
* Schemas registered with the returned generator are converted into TypeScript
|
|
43
|
+
* type aliases and Effect Schema runtime declarations, with reusable OpenAPI
|
|
44
|
+
* component definitions supplied at generation time.
|
|
45
|
+
*
|
|
46
|
+
* @category code generation
|
|
47
|
+
* @since 4.0.0
|
|
48
|
+
*/
|
|
19
49
|
export function make() {
|
|
20
50
|
const store: Record<string, JsonSchema.JsonSchema> = {}
|
|
21
51
|
|
package/src/OpenApiGenerator.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `OpenApiGenerator` module orchestrates converting OpenAPI and Swagger
|
|
3
|
+
* documents into generated Effect source.
|
|
4
|
+
*
|
|
5
|
+
* It normalizes Swagger 2.0 input, resolves local references, builds the
|
|
6
|
+
* parsed operation model, registers request and response schemas, applies
|
|
7
|
+
* HttpApi-specific adaptations such as multipart helpers and security metadata,
|
|
8
|
+
* emits warnings for unsupported or lossy OpenAPI features, and then delegates
|
|
9
|
+
* final rendering to the HttpClient or HttpApi code generators.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
12
|
+
*/
|
|
1
13
|
import * as Context from "effect/Context"
|
|
2
14
|
import * as Effect from "effect/Effect"
|
|
3
15
|
import type * as JsonSchema from "effect/JsonSchema"
|
|
@@ -12,13 +24,32 @@ import * as OpenApiTransformer from "./OpenApiTransformer.ts"
|
|
|
12
24
|
import * as ParsedOperation from "./ParsedOperation.ts"
|
|
13
25
|
import * as Utils from "./Utils.ts"
|
|
14
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Service for turning OpenAPI or Swagger specifications into generated Effect
|
|
29
|
+
* HTTP client or HttpApi source code.
|
|
30
|
+
*
|
|
31
|
+
* @category services
|
|
32
|
+
* @since 4.0.0
|
|
33
|
+
*/
|
|
15
34
|
export class OpenApiGenerator extends Context.Service<
|
|
16
35
|
OpenApiGenerator,
|
|
17
36
|
{ readonly generate: (spec: OpenAPISpec, options: OpenApiGenerateOptions) => Effect.Effect<string> }
|
|
18
37
|
>()("OpenApiGenerator") {}
|
|
19
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Output targets supported by the OpenAPI generator.
|
|
41
|
+
*
|
|
42
|
+
* @category models
|
|
43
|
+
* @since 4.0.0
|
|
44
|
+
*/
|
|
20
45
|
export type OpenApiGeneratorFormat = "httpclient" | "httpclient-type-only" | "httpapi"
|
|
21
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Stable identifiers for non-fatal OpenAPI generation warnings.
|
|
49
|
+
*
|
|
50
|
+
* @category models
|
|
51
|
+
* @since 4.0.0
|
|
52
|
+
*/
|
|
22
53
|
export type OpenApiGeneratorWarningCode =
|
|
23
54
|
| "cookie-parameter-dropped"
|
|
24
55
|
| "additional-tags-dropped"
|
|
@@ -30,6 +61,13 @@ export type OpenApiGeneratorWarningCode =
|
|
|
30
61
|
| "no-body-method-request-body-skipped"
|
|
31
62
|
| "naming-collision"
|
|
32
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Describes a non-fatal issue encountered while mapping an OpenAPI operation to
|
|
66
|
+
* generated Effect source.
|
|
67
|
+
*
|
|
68
|
+
* @category models
|
|
69
|
+
* @since 4.0.0
|
|
70
|
+
*/
|
|
33
71
|
export interface OpenApiGeneratorWarning {
|
|
34
72
|
readonly code: OpenApiGeneratorWarningCode
|
|
35
73
|
readonly message: string
|
|
@@ -38,6 +76,12 @@ export interface OpenApiGeneratorWarning {
|
|
|
38
76
|
readonly operationId?: string | undefined
|
|
39
77
|
}
|
|
40
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Options that control one OpenAPI generation run.
|
|
81
|
+
*
|
|
82
|
+
* @category models
|
|
83
|
+
* @since 4.0.0
|
|
84
|
+
*/
|
|
41
85
|
export interface OpenApiGenerateOptions {
|
|
42
86
|
/**
|
|
43
87
|
* The name to give to the generated output.
|
|
@@ -73,6 +117,12 @@ const methodNames: ReadonlyArray<OpenAPISpecMethodName> = [
|
|
|
73
117
|
"trace"
|
|
74
118
|
]
|
|
75
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Constructs the OpenAPI generator service implementation.
|
|
122
|
+
*
|
|
123
|
+
* @category constructors
|
|
124
|
+
* @since 4.0.0
|
|
125
|
+
*/
|
|
76
126
|
export const make = Effect.gen(function*() {
|
|
77
127
|
const generate = Effect.fn(
|
|
78
128
|
function*(spec: OpenAPISpec, options: OpenApiGenerateOptions) {
|
|
@@ -1018,8 +1068,20 @@ function getDialect(spec: OpenAPISpec): "openapi-3.0" | "openapi-3.1" {
|
|
|
1018
1068
|
return spec.openapi.trim().startsWith("3.0") ? "openapi-3.0" : "openapi-3.1"
|
|
1019
1069
|
}
|
|
1020
1070
|
|
|
1071
|
+
/**
|
|
1072
|
+
* Layer providing an OpenAPI generator for Schema-backed HTTP client and HttpApi output.
|
|
1073
|
+
*
|
|
1074
|
+
* @category layers
|
|
1075
|
+
* @since 4.0.0
|
|
1076
|
+
*/
|
|
1021
1077
|
export const layerTransformerSchema: Layer.Layer<OpenApiGenerator> = Layer.effect(OpenApiGenerator, make)
|
|
1022
1078
|
|
|
1079
|
+
/**
|
|
1080
|
+
* Layer providing an OpenAPI generator for type-only HTTP client output.
|
|
1081
|
+
*
|
|
1082
|
+
* @category layers
|
|
1083
|
+
* @since 4.0.0
|
|
1084
|
+
*/
|
|
1023
1085
|
export const layerTransformerTs: Layer.Layer<OpenApiGenerator> = Layer.effect(OpenApiGenerator, make)
|
|
1024
1086
|
|
|
1025
1087
|
const isSwaggerSpec = (spec: OpenAPISpec) => "swagger" in spec
|
package/src/OpenApiPatch.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - YAML files (.yaml, .yml)
|
|
8
8
|
* - Inline JSON strings
|
|
9
9
|
*
|
|
10
|
-
* @
|
|
10
|
+
* @since 4.0.0
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import * as Effect from "effect/Effect"
|
|
@@ -31,7 +31,8 @@ import * as Yaml from "yaml"
|
|
|
31
31
|
* - JSON or YAML syntax is invalid
|
|
32
32
|
* - The file format is unsupported
|
|
33
33
|
*
|
|
34
|
-
*
|
|
34
|
+
* **Example** (Creating a parse error)
|
|
35
|
+
*
|
|
35
36
|
* ```ts
|
|
36
37
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
37
38
|
*
|
|
@@ -44,8 +45,8 @@ import * as Yaml from "yaml"
|
|
|
44
45
|
* // "Failed to parse patch from ./patches/fix.json: Unexpected token at position 42"
|
|
45
46
|
* ```
|
|
46
47
|
*
|
|
47
|
-
* @since 1.0.0
|
|
48
48
|
* @category errors
|
|
49
|
+
* @since 4.0.0
|
|
49
50
|
*/
|
|
50
51
|
export class JsonPatchParseError extends Schema.ErrorClass<JsonPatchParseError>("JsonPatchParseError")({
|
|
51
52
|
_tag: Schema.tag("JsonPatchParseError"),
|
|
@@ -66,7 +67,8 @@ export class JsonPatchParseError extends Schema.ErrorClass<JsonPatchParseError>(
|
|
|
66
67
|
* - An operation has an unsupported op value
|
|
67
68
|
* - An add/replace operation is missing the value field
|
|
68
69
|
*
|
|
69
|
-
*
|
|
70
|
+
* **Example** (Creating a validation error)
|
|
71
|
+
*
|
|
70
72
|
* ```ts
|
|
71
73
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
72
74
|
*
|
|
@@ -79,8 +81,8 @@ export class JsonPatchParseError extends Schema.ErrorClass<JsonPatchParseError>(
|
|
|
79
81
|
* // "Invalid JSON Patch from inline: Expected 'add' | 'remove' | 'replace' at [0].op, got 'copy'"
|
|
80
82
|
* ```
|
|
81
83
|
*
|
|
82
|
-
* @since 1.0.0
|
|
83
84
|
* @category errors
|
|
85
|
+
* @since 4.0.0
|
|
84
86
|
*/
|
|
85
87
|
export class JsonPatchValidationError extends Schema.ErrorClass<JsonPatchValidationError>("JsonPatchValidationError")({
|
|
86
88
|
_tag: Schema.tag("JsonPatchValidationError"),
|
|
@@ -100,7 +102,8 @@ export class JsonPatchValidationError extends Schema.ErrorClass<JsonPatchValidat
|
|
|
100
102
|
* - An array index is out of bounds
|
|
101
103
|
* - The target location is not a valid container
|
|
102
104
|
*
|
|
103
|
-
*
|
|
105
|
+
* **Example** (Creating an application error)
|
|
106
|
+
*
|
|
104
107
|
* ```ts
|
|
105
108
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
106
109
|
*
|
|
@@ -116,8 +119,8 @@ export class JsonPatchValidationError extends Schema.ErrorClass<JsonPatchValidat
|
|
|
116
119
|
* // "Failed to apply patch from ./patches/fix.json: operation 2 (remove at /paths/~1users): Property \"users\" does not exist"
|
|
117
120
|
* ```
|
|
118
121
|
*
|
|
119
|
-
* @since 1.0.0
|
|
120
122
|
* @category errors
|
|
123
|
+
* @since 4.0.0
|
|
121
124
|
*/
|
|
122
125
|
export class JsonPatchApplicationError
|
|
123
126
|
extends Schema.ErrorClass<JsonPatchApplicationError>("JsonPatchApplicationError")({
|
|
@@ -141,7 +144,8 @@ export class JsonPatchApplicationError
|
|
|
141
144
|
* This error aggregates all application errors so users can see every
|
|
142
145
|
* failing operation at once instead of fixing them one at a time.
|
|
143
146
|
*
|
|
144
|
-
*
|
|
147
|
+
* **Example** (Creating an aggregate error)
|
|
148
|
+
*
|
|
145
149
|
* ```ts
|
|
146
150
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
147
151
|
*
|
|
@@ -168,8 +172,8 @@ export class JsonPatchApplicationError
|
|
|
168
172
|
* // "2 patch operations failed:\n 1. ..."
|
|
169
173
|
* ```
|
|
170
174
|
*
|
|
171
|
-
* @since 1.0.0
|
|
172
175
|
* @category errors
|
|
176
|
+
* @since 4.0.0
|
|
173
177
|
*/
|
|
174
178
|
export class JsonPatchAggregateError extends Schema.ErrorClass<JsonPatchAggregateError>("JsonPatchAggregateError")({
|
|
175
179
|
_tag: Schema.tag("JsonPatchAggregateError"),
|
|
@@ -193,8 +197,8 @@ export class JsonPatchAggregateError extends Schema.ErrorClass<JsonPatchAggregat
|
|
|
193
197
|
/**
|
|
194
198
|
* Schema for a JSON Patch "add" operation.
|
|
195
199
|
*
|
|
196
|
-
* @since 1.0.0
|
|
197
200
|
* @category schemas
|
|
201
|
+
* @since 4.0.0
|
|
198
202
|
*/
|
|
199
203
|
export const JsonPatchAdd: Schema.Codec<
|
|
200
204
|
Extract<
|
|
@@ -211,8 +215,8 @@ export const JsonPatchAdd: Schema.Codec<
|
|
|
211
215
|
/**
|
|
212
216
|
* Schema for a JSON Patch "remove" operation.
|
|
213
217
|
*
|
|
214
|
-
* @since 1.0.0
|
|
215
218
|
* @category schemas
|
|
219
|
+
* @since 4.0.0
|
|
216
220
|
*/
|
|
217
221
|
export const JsonPatchRemove: Schema.Codec<
|
|
218
222
|
Extract<
|
|
@@ -228,8 +232,8 @@ export const JsonPatchRemove: Schema.Codec<
|
|
|
228
232
|
/**
|
|
229
233
|
* Schema for a JSON Patch "replace" operation.
|
|
230
234
|
*
|
|
231
|
-
* @since 1.0.0
|
|
232
235
|
* @category schemas
|
|
236
|
+
* @since 4.0.0
|
|
233
237
|
*/
|
|
234
238
|
export const JsonPatchReplace: Schema.Codec<
|
|
235
239
|
Extract<
|
|
@@ -249,8 +253,8 @@ export const JsonPatchReplace: Schema.Codec<
|
|
|
249
253
|
* Supports the subset of RFC 6902 operations that Effect's JsonPatch module
|
|
250
254
|
* implements: `add`, `remove`, and `replace`.
|
|
251
255
|
*
|
|
252
|
-
* @since 1.0.0
|
|
253
256
|
* @category schemas
|
|
257
|
+
* @since 4.0.0
|
|
254
258
|
*/
|
|
255
259
|
export const JsonPatchOperation: Schema.Codec<JsonPatch.JsonPatchOperation> = Schema.Union([
|
|
256
260
|
JsonPatchAdd,
|
|
@@ -265,7 +269,8 @@ export const JsonPatchOperation: Schema.Codec<JsonPatch.JsonPatchOperation> = Sc
|
|
|
265
269
|
* document. Operations are applied in sequence, with each operation seeing
|
|
266
270
|
* the result of previous operations.
|
|
267
271
|
*
|
|
268
|
-
*
|
|
272
|
+
* **Example** (Decoding a patch document)
|
|
273
|
+
*
|
|
269
274
|
* ```ts
|
|
270
275
|
* import { Schema } from "effect"
|
|
271
276
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
@@ -277,16 +282,16 @@ export const JsonPatchOperation: Schema.Codec<JsonPatch.JsonPatchOperation> = Sc
|
|
|
277
282
|
* ])
|
|
278
283
|
* ```
|
|
279
284
|
*
|
|
280
|
-
* @since 1.0.0
|
|
281
285
|
* @category schemas
|
|
286
|
+
* @since 4.0.0
|
|
282
287
|
*/
|
|
283
288
|
export const JsonPatchDocument = Schema.Array(JsonPatchOperation)
|
|
284
289
|
|
|
285
290
|
/**
|
|
286
291
|
* Type for a JSON Patch document.
|
|
287
292
|
*
|
|
288
|
-
* @since 1.0.0
|
|
289
293
|
* @category types
|
|
294
|
+
* @since 4.0.0
|
|
290
295
|
*/
|
|
291
296
|
export type JsonPatchDocument = typeof JsonPatchDocument.Type
|
|
292
297
|
|
|
@@ -413,7 +418,8 @@ const parseInlinePatch = Effect.fn("parseInlinePatch")(function*(input: string)
|
|
|
413
418
|
* and parsed based on its extension (.json, .yaml, .yml). Otherwise, the
|
|
414
419
|
* input is parsed as inline JSON.
|
|
415
420
|
*
|
|
416
|
-
*
|
|
421
|
+
* **Example** (Parsing patch input)
|
|
422
|
+
*
|
|
417
423
|
* ```ts
|
|
418
424
|
* import { Effect } from "effect"
|
|
419
425
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
@@ -433,8 +439,8 @@ const parseInlinePatch = Effect.fn("parseInlinePatch")(function*(input: string)
|
|
|
433
439
|
* })
|
|
434
440
|
* ```
|
|
435
441
|
*
|
|
436
|
-
* @since 1.0.0
|
|
437
442
|
* @category parsing
|
|
443
|
+
* @since 4.0.0
|
|
438
444
|
*/
|
|
439
445
|
export const parsePatchInput = Effect.fn("parsePatchInput")(function*(input: string) {
|
|
440
446
|
if (looksLikeFilePath(input)) {
|
|
@@ -457,7 +463,8 @@ export const parsePatchInput = Effect.fn("parsePatchInput")(function*(input: str
|
|
|
457
463
|
* the previous one. All operations are attempted, and if any fail, the errors
|
|
458
464
|
* are accumulated and reported together so users can fix all issues at once.
|
|
459
465
|
*
|
|
460
|
-
*
|
|
466
|
+
* **Example** (Applying patches)
|
|
467
|
+
*
|
|
461
468
|
* ```ts
|
|
462
469
|
* import { Effect } from "effect"
|
|
463
470
|
* import * as OpenApiPatch from "@effect/openapi-generator/OpenApiPatch"
|
|
@@ -477,8 +484,8 @@ export const parsePatchInput = Effect.fn("parsePatchInput")(function*(input: str
|
|
|
477
484
|
* })
|
|
478
485
|
* ```
|
|
479
486
|
*
|
|
480
|
-
* @since 1.0.0
|
|
481
487
|
* @category application
|
|
488
|
+
* @since 4.0.0
|
|
482
489
|
*/
|
|
483
490
|
export const applyPatches = Effect.fn("applyPatches")(function*(
|
|
484
491
|
patches: ReadonlyArray<{ readonly source: string; readonly patch: JsonPatchDocument }>,
|
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI-to-HttpClient code generation for the OpenAPI generator.
|
|
3
|
+
*
|
|
4
|
+
* This module defines the `OpenApiTransformer` service used to render parsed
|
|
5
|
+
* OpenAPI operations into Effect `HttpClient` modules. It provides both
|
|
6
|
+
* schema-backed and type-only transformer implementations, including generated
|
|
7
|
+
* imports, public client interfaces, operation implementations, typed API
|
|
8
|
+
* errors, optional response handling, and helpers for server-sent events and
|
|
9
|
+
* binary response streams.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
12
|
+
*/
|
|
1
13
|
import * as Context from "effect/Context"
|
|
2
14
|
import * as Layer from "effect/Layer"
|
|
3
15
|
import * as Predicate from "effect/Predicate"
|
|
4
16
|
import type { ParsedOpenApi, ParsedOperation } from "./ParsedOperation.ts"
|
|
5
17
|
import * as Utils from "./Utils.ts"
|
|
6
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Service used by the OpenAPI generator to render parsed operations as an
|
|
21
|
+
* Effect HttpClient module.
|
|
22
|
+
*
|
|
23
|
+
* A transformer owns the code-generation dialect for imports, public client
|
|
24
|
+
* types, and the implementation body. The generator swaps implementations to
|
|
25
|
+
* choose between schema-backed clients and type-only clients.
|
|
26
|
+
*
|
|
27
|
+
* @category code generation
|
|
28
|
+
* @since 4.0.0
|
|
29
|
+
*/
|
|
7
30
|
export class OpenApiTransformer extends Context.Service<
|
|
8
31
|
OpenApiTransformer,
|
|
9
32
|
{
|
|
@@ -35,6 +58,16 @@ const computeImportRequirements = (operations: ReadonlyArray<ParsedOperation>):
|
|
|
35
58
|
const requiresStreaming = (requirements: ImportRequirements): boolean =>
|
|
36
59
|
requirements.eventStream || requirements.octetStream
|
|
37
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Create the transformer used for schema-backed HttpClient output.
|
|
63
|
+
*
|
|
64
|
+
* Generated clients import Effect Schema values and use them at runtime to
|
|
65
|
+
* decode successful responses and typed API errors. Request parameters and
|
|
66
|
+
* payloads are typed against each schema's encoded representation.
|
|
67
|
+
*
|
|
68
|
+
* @category code generation
|
|
69
|
+
* @since 4.0.0
|
|
70
|
+
*/
|
|
38
71
|
export const makeTransformerSchema = () => {
|
|
39
72
|
const operationsToInterface = (
|
|
40
73
|
_importName: string,
|
|
@@ -417,11 +450,31 @@ export const make = (
|
|
|
417
450
|
})
|
|
418
451
|
}
|
|
419
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Layer that provides the schema-backed OpenApiTransformer service.
|
|
455
|
+
*
|
|
456
|
+
* Use this layer when generated HttpClient code should perform runtime response
|
|
457
|
+
* decoding with generated Effect Schema values.
|
|
458
|
+
*
|
|
459
|
+
* @category code generation
|
|
460
|
+
* @since 4.0.0
|
|
461
|
+
*/
|
|
420
462
|
export const layerTransformerSchema = Layer.sync(
|
|
421
463
|
OpenApiTransformer,
|
|
422
464
|
makeTransformerSchema
|
|
423
465
|
)
|
|
424
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Create the transformer used for type-only HttpClient output.
|
|
469
|
+
*
|
|
470
|
+
* Generated clients reference emitted TypeScript types directly and do not
|
|
471
|
+
* import schema decoders for JSON response bodies. Responses are typed as the
|
|
472
|
+
* declared operation result while preserving generated error and stream method
|
|
473
|
+
* shapes.
|
|
474
|
+
*
|
|
475
|
+
* @category code generation
|
|
476
|
+
* @since 4.0.0
|
|
477
|
+
*/
|
|
425
478
|
export const makeTransformerTs = () => {
|
|
426
479
|
const operationsToInterface = (
|
|
427
480
|
_importName: string,
|
|
@@ -803,6 +856,16 @@ export const make = (
|
|
|
803
856
|
})
|
|
804
857
|
}
|
|
805
858
|
|
|
859
|
+
/**
|
|
860
|
+
* Layer that provides the type-only OpenApiTransformer service.
|
|
861
|
+
*
|
|
862
|
+
* Use this layer for the `httpclient-type-only` generator format, where the
|
|
863
|
+
* generated client relies on TypeScript types instead of runtime Schema
|
|
864
|
+
* decoding.
|
|
865
|
+
*
|
|
866
|
+
* @category code generation
|
|
867
|
+
* @since 4.0.0
|
|
868
|
+
*/
|
|
806
869
|
export const layerTransformerTs = Layer.sync(
|
|
807
870
|
OpenApiTransformer,
|
|
808
871
|
makeTransformerTs
|
package/src/ParsedOperation.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalized OpenAPI operation model shared by the generator pipeline.
|
|
3
|
+
*
|
|
4
|
+
* This module records the shape produced after an OpenAPI document is resolved
|
|
5
|
+
* into stable generator inputs: document metadata, tags, security schemes,
|
|
6
|
+
* per-operation parameters, request bodies, response media types, derived
|
|
7
|
+
* schema references, path templates, and streaming capabilities. Renderers
|
|
8
|
+
* consume this representation to emit HttpClient or HttpApi modules without
|
|
9
|
+
* reinterpreting raw OpenAPI path-item structures.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
12
|
+
*/
|
|
1
13
|
import type * as Types from "effect/Types"
|
|
2
14
|
import type {
|
|
3
15
|
OpenAPISecurityRequirement,
|
|
@@ -7,6 +19,12 @@ import type {
|
|
|
7
19
|
OpenAPISpecServer
|
|
8
20
|
} from "effect/unstable/httpapi/OpenApi"
|
|
9
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Root OpenAPI metadata preserved for generated client and HttpApi output.
|
|
24
|
+
*
|
|
25
|
+
* @category models
|
|
26
|
+
* @since 4.0.0
|
|
27
|
+
*/
|
|
10
28
|
export interface ParsedOpenApiMetadata {
|
|
11
29
|
readonly title: string
|
|
12
30
|
readonly version: string
|
|
@@ -16,12 +34,24 @@ export interface ParsedOpenApiMetadata {
|
|
|
16
34
|
readonly servers: ReadonlyArray<OpenAPISpecServer> | undefined
|
|
17
35
|
}
|
|
18
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Tag metadata used to group and annotate generated operations.
|
|
39
|
+
*
|
|
40
|
+
* @category models
|
|
41
|
+
* @since 4.0.0
|
|
42
|
+
*/
|
|
19
43
|
export interface ParsedOpenApiTag {
|
|
20
44
|
readonly name: string
|
|
21
45
|
readonly description: string | undefined
|
|
22
46
|
readonly externalDocs: OpenAPISpecExternalDocs | undefined
|
|
23
47
|
}
|
|
24
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Supported security scheme extracted from an OpenAPI components section.
|
|
51
|
+
*
|
|
52
|
+
* @category models
|
|
53
|
+
* @since 4.0.0
|
|
54
|
+
*/
|
|
25
55
|
export interface ParsedOpenApiSecurityScheme {
|
|
26
56
|
readonly name: string
|
|
27
57
|
readonly type: "basic" | "bearer" | "apiKey"
|
|
@@ -31,6 +61,12 @@ export interface ParsedOpenApiSecurityScheme {
|
|
|
31
61
|
readonly in: "header" | "query" | "cookie" | undefined
|
|
32
62
|
}
|
|
33
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Normalized OpenAPI document consumed by the generator renderers.
|
|
66
|
+
*
|
|
67
|
+
* @category models
|
|
68
|
+
* @since 4.0.0
|
|
69
|
+
*/
|
|
34
70
|
export interface ParsedOpenApi {
|
|
35
71
|
readonly metadata: ParsedOpenApiMetadata
|
|
36
72
|
readonly tags: ReadonlyArray<ParsedOpenApiTag>
|
|
@@ -38,6 +74,12 @@ export interface ParsedOpenApi {
|
|
|
38
74
|
readonly operations: ReadonlyArray<ParsedOperation>
|
|
39
75
|
}
|
|
40
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Documentation and lifecycle metadata associated with an operation.
|
|
79
|
+
*
|
|
80
|
+
* @category models
|
|
81
|
+
* @since 4.0.0
|
|
82
|
+
*/
|
|
41
83
|
export interface ParsedOperationMetadata {
|
|
42
84
|
readonly summary: string | undefined
|
|
43
85
|
readonly description: string | undefined
|
|
@@ -45,6 +87,12 @@ export interface ParsedOperationMetadata {
|
|
|
45
87
|
readonly externalDocs: OpenAPISpecExternalDocs | undefined
|
|
46
88
|
}
|
|
47
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Resolved OpenAPI parameter grouped by where it appears in the request.
|
|
92
|
+
*
|
|
93
|
+
* @category models
|
|
94
|
+
* @since 4.0.0
|
|
95
|
+
*/
|
|
48
96
|
export interface ParsedOperationParameter {
|
|
49
97
|
readonly name: string
|
|
50
98
|
readonly in: "path" | "query" | "header" | "cookie"
|
|
@@ -53,11 +101,23 @@ export interface ParsedOperationParameter {
|
|
|
53
101
|
readonly schema: {}
|
|
54
102
|
}
|
|
55
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Summary of the request body declaration before per-media schemas are rendered.
|
|
106
|
+
*
|
|
107
|
+
* @category models
|
|
108
|
+
* @since 4.0.0
|
|
109
|
+
*/
|
|
56
110
|
export interface ParsedOperationRequestBody {
|
|
57
111
|
readonly required: boolean
|
|
58
112
|
readonly contentTypes: Array<string>
|
|
59
113
|
}
|
|
60
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Encoding strategy the generator can use for a request or response media type.
|
|
117
|
+
*
|
|
118
|
+
* @category models
|
|
119
|
+
* @since 4.0.0
|
|
120
|
+
*/
|
|
61
121
|
export type ParsedOperationMediaTypeEncoding =
|
|
62
122
|
| "json"
|
|
63
123
|
| "multipart"
|
|
@@ -65,12 +125,24 @@ export type ParsedOperationMediaTypeEncoding =
|
|
|
65
125
|
| "text"
|
|
66
126
|
| "binary"
|
|
67
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Media type whose schema can be represented in generated Effect code.
|
|
130
|
+
*
|
|
131
|
+
* @category models
|
|
132
|
+
* @since 4.0.0
|
|
133
|
+
*/
|
|
68
134
|
export interface ParsedOperationMediaTypeSchema {
|
|
69
135
|
readonly contentType: string
|
|
70
136
|
readonly encoding: ParsedOperationMediaTypeEncoding
|
|
71
137
|
readonly schema: string
|
|
72
138
|
}
|
|
73
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Parsed response metadata together with generated schema references.
|
|
142
|
+
*
|
|
143
|
+
* @category models
|
|
144
|
+
* @since 4.0.0
|
|
145
|
+
*/
|
|
74
146
|
export interface ParsedOperationResponse {
|
|
75
147
|
readonly status: string
|
|
76
148
|
readonly description: string | undefined
|
|
@@ -80,8 +152,20 @@ export interface ParsedOperationResponse {
|
|
|
80
152
|
readonly representable: ReadonlyArray<ParsedOperationMediaTypeSchema>
|
|
81
153
|
}
|
|
82
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Resolved security requirement applied to a parsed operation.
|
|
157
|
+
*
|
|
158
|
+
* @category models
|
|
159
|
+
* @since 4.0.0
|
|
160
|
+
*/
|
|
83
161
|
export type ParsedOperationSecurityRequirement = Readonly<OpenAPISecurityRequirement>
|
|
84
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Normalized operation model shared by all OpenAPI generator backends.
|
|
165
|
+
*
|
|
166
|
+
* @category models
|
|
167
|
+
* @since 4.0.0
|
|
168
|
+
*/
|
|
85
169
|
export interface ParsedOperation {
|
|
86
170
|
readonly id: string
|
|
87
171
|
readonly operationId: string | undefined
|
|
@@ -125,6 +209,12 @@ export interface ParsedOperation {
|
|
|
125
209
|
readonly binaryResponse: boolean
|
|
126
210
|
}
|
|
127
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Creates a mutable operation accumulator populated with parser defaults.
|
|
214
|
+
*
|
|
215
|
+
* @category constructors
|
|
216
|
+
* @since 4.0.0
|
|
217
|
+
*/
|
|
128
218
|
export const makeDeepMutable = (options: {
|
|
129
219
|
readonly id: string
|
|
130
220
|
readonly method: OpenAPISpecMethodName
|
package/src/Utils.ts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility helpers for the OpenAPI generator.
|
|
3
|
+
*
|
|
4
|
+
* This module centralizes the small transformations used while rendering
|
|
5
|
+
* generated TypeScript, including operation-name normalization, optional
|
|
6
|
+
* description handling, safe JSDoc comment emission, and direct array merging
|
|
7
|
+
* for code-generation accumulators.
|
|
8
|
+
*
|
|
9
|
+
* @since 4.0.0
|
|
10
|
+
*/
|
|
1
11
|
import * as String from "effect/String"
|
|
2
12
|
import * as UndefinedOr from "effect/UndefinedOr"
|
|
3
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Converts an OpenAPI name into the generator's camel-case form.
|
|
16
|
+
*
|
|
17
|
+
* Separators are removed, leading digits are ignored, and letters following a
|
|
18
|
+
* separator or digit are upper-cased without otherwise changing letter casing.
|
|
19
|
+
*
|
|
20
|
+
* @category converting
|
|
21
|
+
* @since 4.0.0
|
|
22
|
+
*/
|
|
4
23
|
export const camelize = (self: string): string => {
|
|
5
24
|
let str = ""
|
|
6
25
|
let hadSymbol = false
|
|
@@ -24,8 +43,24 @@ export const camelize = (self: string): string => {
|
|
|
24
43
|
return str
|
|
25
44
|
}
|
|
26
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Converts an OpenAPI operation id into the exported operation identifier used
|
|
48
|
+
* by generated TypeScript modules.
|
|
49
|
+
*
|
|
50
|
+
* @category converting
|
|
51
|
+
* @since 4.0.0
|
|
52
|
+
*/
|
|
27
53
|
export const identifier = (operationId: string) => String.capitalize(camelize(operationId))
|
|
28
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Extracts a trimmed, non-empty string from an unknown value.
|
|
57
|
+
*
|
|
58
|
+
* Returns `undefined` for non-string values and for strings containing only
|
|
59
|
+
* whitespace.
|
|
60
|
+
*
|
|
61
|
+
* @category filtering
|
|
62
|
+
* @since 4.0.0
|
|
63
|
+
*/
|
|
29
64
|
export const nonEmptyString = (a: unknown): string | undefined => {
|
|
30
65
|
if (typeof a === "string") {
|
|
31
66
|
const trimmed = String.trim(a)
|
|
@@ -35,6 +70,15 @@ export const nonEmptyString = (a: unknown): string | undefined => {
|
|
|
35
70
|
}
|
|
36
71
|
}
|
|
37
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Renders an optional description as a JSDoc block for generated TypeScript.
|
|
75
|
+
*
|
|
76
|
+
* Returns an empty string when the description is absent and escapes any
|
|
77
|
+
* closing comment marker so generated source remains syntactically valid.
|
|
78
|
+
*
|
|
79
|
+
* @category converting
|
|
80
|
+
* @since 4.0.0
|
|
81
|
+
*/
|
|
38
82
|
export const toComment = UndefinedOr.match({
|
|
39
83
|
onUndefined: () => "",
|
|
40
84
|
onDefined: (description: string) =>
|
|
@@ -43,6 +87,15 @@ export const toComment = UndefinedOr.match({
|
|
|
43
87
|
*/\n`
|
|
44
88
|
})
|
|
45
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Appends every element from `source` into `destination` in order.
|
|
92
|
+
*
|
|
93
|
+
* This mutates `destination` directly, which avoids allocating an intermediate
|
|
94
|
+
* array when generator code needs to merge collections.
|
|
95
|
+
*
|
|
96
|
+
* @category concatenating
|
|
97
|
+
* @since 4.0.0
|
|
98
|
+
*/
|
|
46
99
|
export const spreadElementsInto = <A>(source: Array<A>, destination: Array<A>): void => {
|
|
47
100
|
for (let i = 0; i < source.length; i++) {
|
|
48
101
|
destination.push(source[i])
|