@f3liz/rescript-autogen-openapi 0.1.6 → 0.2.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.

Potentially problematic release.


This version of @f3liz/rescript-autogen-openapi might be problematic. Click here for more details.

@@ -75,7 +75,23 @@ function generateTypeWithContext(ctx, depthOpt, irType) {
75
75
  }
76
76
  case "Union" :
77
77
  let types = irType._0;
78
- let match = Stdlib_Array.reduce(types, [
78
+ let nonNullTypes = types.filter(t => {
79
+ if (typeof t !== "object") {
80
+ return t !== "Null";
81
+ }
82
+ if (t.TAG !== "Literal") {
83
+ return true;
84
+ }
85
+ let tmp = t._0;
86
+ return typeof tmp === "object";
87
+ });
88
+ let hasNull = nonNullTypes.length < types.length;
89
+ if (hasNull && nonNullTypes.length === 1) {
90
+ let inner = recurse(nonNullTypes[0]);
91
+ return `option<` + inner + `>`;
92
+ }
93
+ let effectiveTypes = hasNull ? nonNullTypes : types;
94
+ let match = Stdlib_Array.reduce(effectiveTypes, [
79
95
  false,
80
96
  false,
81
97
  undefined,
@@ -100,10 +116,10 @@ function generateTypeWithContext(ctx, depthOpt, irType) {
100
116
  }
101
117
  });
102
118
  let arrayItemType = match[2];
103
- if (match[0] && match[1] && SchemaIR.equals(Stdlib_Option.getOr(arrayItemType, "Unknown"), Stdlib_Option.getOr(match[3], "Unknown"))) {
104
- return `array<` + recurse(Stdlib_Option.getOr(arrayItemType, "Unknown")) + `>`;
105
- }
106
- if (types.every(t => {
119
+ let result;
120
+ if (match[0] && match[1] && effectiveTypes.length === 2 && SchemaIR.equals(Stdlib_Option.getOr(arrayItemType, "Unknown"), Stdlib_Option.getOr(match[3], "Unknown"))) {
121
+ result = `array<` + recurse(Stdlib_Option.getOr(arrayItemType, "Unknown")) + `>`;
122
+ } else if (effectiveTypes.every(t => {
107
123
  if (typeof t !== "object") {
108
124
  return false;
109
125
  }
@@ -116,8 +132,8 @@ function generateTypeWithContext(ctx, depthOpt, irType) {
116
132
  } else {
117
133
  return tmp.TAG === "StringLiteral";
118
134
  }
119
- }) && types.length !== 0 && types.length <= 50) {
120
- let variants = types.map(t => {
135
+ }) && effectiveTypes.length !== 0 && effectiveTypes.length <= 50) {
136
+ let variants = effectiveTypes.map(t => {
121
137
  if (typeof t !== "object") {
122
138
  return "#Unknown";
123
139
  }
@@ -131,26 +147,155 @@ function generateTypeWithContext(ctx, depthOpt, irType) {
131
147
  return `#` + JsConvertCase.toPascalCase(s._0);
132
148
  }
133
149
  }).join(" | ");
134
- return `[` + variants + `]`;
150
+ result = `[` + variants + `]`;
151
+ } else if (effectiveTypes.length !== 0) {
152
+ let hasPrimitives = {
153
+ contents: false
154
+ };
155
+ let variantCases = effectiveTypes.map((t, i) => {
156
+ let match;
157
+ let exit = 0;
158
+ if (typeof t !== "object") {
159
+ if (t === "Boolean") {
160
+ hasPrimitives.contents = true;
161
+ match = [
162
+ "Bool",
163
+ "bool"
164
+ ];
165
+ } else {
166
+ exit = 1;
167
+ }
168
+ } else {
169
+ switch (t.TAG) {
170
+ case "String" :
171
+ hasPrimitives.contents = true;
172
+ match = [
173
+ "String",
174
+ "string"
175
+ ];
176
+ break;
177
+ case "Number" :
178
+ hasPrimitives.contents = true;
179
+ match = [
180
+ "Float",
181
+ "float"
182
+ ];
183
+ break;
184
+ case "Integer" :
185
+ hasPrimitives.contents = true;
186
+ match = [
187
+ "Int",
188
+ "int"
189
+ ];
190
+ break;
191
+ case "Array" :
192
+ match = [
193
+ "Array",
194
+ `array<` + recurse(t.items) + `>`
195
+ ];
196
+ break;
197
+ case "Object" :
198
+ match = [
199
+ "Object",
200
+ recurse(t)
201
+ ];
202
+ break;
203
+ case "Reference" :
204
+ let ref = t._0;
205
+ let name = Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "");
206
+ match = [
207
+ JsConvertCase.toPascalCase(name),
208
+ recurse(t)
209
+ ];
210
+ break;
211
+ default:
212
+ exit = 1;
213
+ }
214
+ }
215
+ if (exit === 1) {
216
+ match = [
217
+ `V` + i.toString(),
218
+ recurse(t)
219
+ ];
220
+ }
221
+ return ` | ` + match[0] + `(` + match[1] + `)`;
222
+ });
223
+ let unboxedAttr = hasPrimitives.contents ? "@unboxed " : "";
224
+ result = unboxedAttr + `[\n` + variantCases.join("\n") + `\n]`;
225
+ } else {
226
+ result = "JSON.t";
227
+ }
228
+ if (hasNull) {
229
+ return `option<` + result + `>`;
230
+ } else {
231
+ return result;
135
232
  }
136
- GenerationContext.addWarning(ctx, {
137
- TAG: "ComplexUnionSimplified",
138
- location: ctx.path,
139
- types: types.map(SchemaIR.toString).join(" | ")
140
- });
141
- return "JSON.t";
142
233
  case "Intersection" :
143
234
  let types$1 = irType._0;
144
- if (types$1.every(t => typeof t !== "object" ? false : t.TAG === "Reference") && types$1.length !== 0) {
235
+ if (types$1.every(t => {
236
+ if (typeof t !== "object") {
237
+ return false;
238
+ } else {
239
+ return t.TAG === "Reference";
240
+ }
241
+ }) && types$1.length !== 0) {
145
242
  return recurse(Stdlib_Option.getOr(types$1[types$1.length - 1 | 0], "Unknown"));
146
- } else {
147
- GenerationContext.addWarning(ctx, {
148
- TAG: "IntersectionNotFullySupported",
149
- location: ctx.path,
150
- note: "Complex intersection"
151
- });
152
- return "JSON.t";
153
243
  }
244
+ let match$1 = Stdlib_Array.reduce(types$1, [
245
+ [],
246
+ []
247
+ ], (param, t) => {
248
+ let nonObj = param[1];
249
+ let props = param[0];
250
+ if (typeof t !== "object") {
251
+ return [
252
+ props,
253
+ nonObj.concat([t])
254
+ ];
255
+ } else if (t.TAG === "Object") {
256
+ return [
257
+ props.concat(t.properties),
258
+ nonObj
259
+ ];
260
+ } else {
261
+ return [
262
+ props,
263
+ nonObj.concat([t])
264
+ ];
265
+ }
266
+ });
267
+ let nonObjectTypes = match$1[1];
268
+ let objectProps = match$1[0];
269
+ if (objectProps.length !== 0 && nonObjectTypes.length === 0) {
270
+ let fields$1 = objectProps.map(param => {
271
+ let name = param[0];
272
+ let typeCode = recurse(param[1]);
273
+ let finalType = param[2] ? typeCode : `option<` + typeCode + `>`;
274
+ let camelName = JsConvertCase.toCamelCase(name);
275
+ let escapedName = CodegenUtils.escapeKeyword(camelName);
276
+ let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
277
+ return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
278
+ }).join("\n");
279
+ return `{\n` + fields$1 + `\n}`;
280
+ }
281
+ if (nonObjectTypes.length !== 0 && objectProps.length === 0) {
282
+ return recurse(Stdlib_Option.getOr(types$1[types$1.length - 1 | 0], "Unknown"));
283
+ }
284
+ GenerationContext.addWarning(ctx, {
285
+ TAG: "IntersectionNotFullySupported",
286
+ location: ctx.path,
287
+ note: "Mixed object/non-object intersection"
288
+ });
289
+ let fields$2 = objectProps.map(param => {
290
+ let name = param[0];
291
+ let typeCode = recurse(param[1]);
292
+ let finalType = param[2] ? typeCode : `option<` + typeCode + `>`;
293
+ let camelName = JsConvertCase.toCamelCase(name);
294
+ let escapedName = CodegenUtils.escapeKeyword(camelName);
295
+ let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
296
+ return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
297
+ }).join("\n");
298
+ return `{\n` + fields$2 + `\n}`;
154
299
  case "Reference" :
155
300
  let ref = irType._0;
156
301
  let available = ctx.availableSchemas;
@@ -0,0 +1,66 @@
1
+ export type context = {
2
+ readonly path: string;
3
+ readonly operation: string;
4
+ readonly schema: (undefined | unknown);
5
+ };
6
+ export type t = {
7
+ TAG: "SpecResolutionError";
8
+ readonly url: string;
9
+ readonly message: string;
10
+ } | {
11
+ TAG: "SchemaParseError";
12
+ readonly context: context;
13
+ readonly reason: string;
14
+ } | {
15
+ TAG: "ReferenceError";
16
+ readonly ref: string;
17
+ readonly context: context;
18
+ } | {
19
+ TAG: "ValidationError";
20
+ readonly schema: string;
21
+ readonly input: unknown;
22
+ readonly issues: string[];
23
+ } | {
24
+ TAG: "CircularSchemaError";
25
+ readonly ref: string;
26
+ readonly depth: number;
27
+ readonly path: string;
28
+ } | {
29
+ TAG: "FileWriteError";
30
+ readonly filePath: string;
31
+ readonly message: string;
32
+ } | {
33
+ TAG: "InvalidConfigError";
34
+ readonly field: string;
35
+ readonly message: string;
36
+ } | {
37
+ TAG: "UnknownError";
38
+ readonly message: string;
39
+ readonly context: (undefined | context);
40
+ };
41
+ export type Warning_t = {
42
+ TAG: "FallbackToJson";
43
+ readonly reason: string;
44
+ readonly context: context;
45
+ } | {
46
+ TAG: "UnsupportedFeature";
47
+ readonly feature: string;
48
+ readonly fallback: string;
49
+ readonly location: string;
50
+ } | {
51
+ TAG: "DepthLimitReached";
52
+ readonly depth: number;
53
+ readonly path: string;
54
+ } | {
55
+ TAG: "MissingSchema";
56
+ readonly ref: string;
57
+ readonly location: string;
58
+ } | {
59
+ TAG: "IntersectionNotFullySupported";
60
+ readonly location: string;
61
+ readonly note: string;
62
+ } | {
63
+ TAG: "ComplexUnionSimplified";
64
+ readonly location: string;
65
+ readonly types: string;
66
+ };
@@ -0,0 +1,31 @@
1
+ export type generationStrategy = "Separate" | "SharedBase";
2
+ export type breakingChangeHandling = "Error" | "Warn" | "Ignore";
3
+ export type forkSpecConfig = {
4
+ readonly name: string;
5
+ readonly specPath: string;
6
+ };
7
+ export type generationTargets = {
8
+ readonly rescriptApi: boolean;
9
+ readonly rescriptWrapper: boolean;
10
+ readonly typescriptDts: boolean;
11
+ readonly typescriptWrapper: boolean;
12
+ };
13
+ export type t = {
14
+ readonly specPath: string;
15
+ readonly forkSpecs: (undefined | forkSpecConfig[]);
16
+ readonly outputDir: string;
17
+ readonly strategy: generationStrategy;
18
+ readonly modulePerTag: boolean;
19
+ readonly includeTags: (undefined | string[]);
20
+ readonly excludeTags: (undefined | string[]);
21
+ readonly generateDiffReport: boolean;
22
+ readonly breakingChangeHandling: breakingChangeHandling;
23
+ readonly generateDocOverrides: (undefined | boolean);
24
+ readonly docOverrideDir: (undefined | string);
25
+ readonly targets: (undefined | generationTargets);
26
+ readonly dtsOutputDir: (undefined | string);
27
+ readonly wrapperOutputDir: (undefined | string);
28
+ readonly baseInstanceName: (undefined | string);
29
+ readonly baseModulePrefix: (undefined | string);
30
+ };
31
+ export declare const make: (specPath: string, outputDir: string, strategy: (undefined | generationStrategy), modulePerTag: (undefined | boolean), includeTags: (undefined | string[]), excludeTags: (undefined | string[]), generateDiffReport: (undefined | boolean), breakingChangeHandling: (undefined | breakingChangeHandling), forkSpecs: (undefined | forkSpecConfig[]), generateDocOverrides: (undefined | boolean), docOverrideDir: (undefined | string), targets: (undefined | generationTargets), dtsOutputDir: (undefined | string), wrapperOutputDir: (undefined | string), baseInstanceName: (undefined | string), baseModulePrefix: (undefined | string), _17: void) => t;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@f3liz/rescript-autogen-openapi",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "Generate ReScript code with Sury schemas from OpenAPI 3.1 specs. Supports multiple forks with diff/merge capabilities.",
5
5
  "keywords": [
6
6
  "rescript",
@@ -16,7 +16,8 @@
16
16
  "license": "MPL-2.0",
17
17
  "files": [
18
18
  "src/**/*.res",
19
- "lib/es6/**/*.mjs",
19
+ "lib/es6/src/**/*.mjs",
20
+ "lib/es6/src/**/*.d.ts",
20
21
  "rescript.json",
21
22
  "README.md",
22
23
  "LICENSE"
@@ -25,23 +26,27 @@
25
26
  "url": "https://github.com/f3liz-dev/rescript-autogen-openapi"
26
27
  },
27
28
  "scripts": {
28
- "build": "rescript",
29
+ "build": "rescript && node scripts/generate-dts.mjs",
29
30
  "clean": "rescript clean",
30
31
  "watch": "rescript build -w",
31
- "test": "node --test"
32
+ "test": "node --test",
33
+ "prepublishOnly": "npm run build && npm test"
32
34
  },
33
35
  "main": "lib/es6/src/Codegen.mjs",
36
+ "types": "lib/es6/src/Codegen.d.ts",
34
37
  "type": "module",
35
38
  "dependencies": {
36
39
  "@readme/openapi-parser": "^5.5.0",
37
40
  "js-convert-case": "^4.2.0",
38
- "pathe": "^2.0.3",
39
- "sury": "11.0.0-alpha.4"
41
+ "pathe": "^2.0.3"
40
42
  },
41
43
  "devDependencies": {
42
- "rescript": "^12.1.0"
44
+ "rescript": "^12.1.0",
45
+ "sury": "11.0.0-alpha.4",
46
+ "typescript": "^5.9.3"
43
47
  },
44
48
  "peerDependencies": {
45
- "rescript": "^12.0.0"
49
+ "rescript": "^12.0.0",
50
+ "sury": ">=11.0.0-alpha.4"
46
51
  }
47
52
  }
package/rescript.json CHANGED
@@ -13,6 +13,12 @@
13
13
  }
14
14
  ],
15
15
  "suffix": ".mjs",
16
+ "gentypeconfig": {
17
+ "language": "typescript",
18
+ "module": "es6",
19
+ "importPath": "relative",
20
+ "generatedFileExtension": ".gen.ts"
21
+ },
16
22
  "dependencies": [],
17
23
  "warnings": {
18
24
  "number": "-44-102"
package/src/Codegen.res CHANGED
@@ -7,6 +7,7 @@ open Types
7
7
  @val external promiseAll: array<promise<'a>> => promise<array<'a>> = "Promise.all"
8
8
 
9
9
  // Generate code from a single spec (pure - returns data)
10
+ @genType
10
11
  let generateSingleSpecPure = (~spec: openAPISpec, ~config: generationConfig): result<Pipeline.t, codegenError> => {
11
12
  try {
12
13
  let targets = config.targets->Option.getOr(Config.defaultTargets())
@@ -54,6 +55,7 @@ let generateSingleSpecPure = (~spec: openAPISpec, ~config: generationConfig): re
54
55
  }
55
56
 
56
57
  // Generate code from a single spec (with side effects)
58
+ @genType
57
59
  let generateSingleSpec = async (~spec: openAPISpec, ~config: generationConfig): generationResult => {
58
60
  switch generateSingleSpecPure(~spec, ~config) {
59
61
  | Result.Error(err) => Result.Error(err)
@@ -140,6 +142,7 @@ let processForkPure = (~baseSpec: openAPISpec, ~baseEndpoints: array<endpoint>,
140
142
  }
141
143
 
142
144
  // Generate code from multiple specs (pure - returns data)
145
+ @genType
143
146
  let generateMultiSpecPure = (~baseSpec: openAPISpec, ~forkSpecs: array<forkSpec>, ~config: generationConfig): result<Pipeline.t, codegenError> => {
144
147
  try {
145
148
  let baseEndpoints = OpenAPIParser.getAllEndpoints(baseSpec)
@@ -169,6 +172,7 @@ let generateMultiSpecPure = (~baseSpec: openAPISpec, ~forkSpecs: array<forkSpec>
169
172
  }
170
173
 
171
174
  // Generate code from multiple specs (with side effects)
175
+ @genType
172
176
  let generateMultiSpec = async (~baseSpec: openAPISpec, ~forkSpecs: array<forkSpec>, ~config: generationConfig): generationResult =>
173
177
  switch generateMultiSpecPure(~baseSpec, ~forkSpecs, ~config) {
174
178
  | Result.Error(err) => Result.Error(err)
@@ -179,6 +183,7 @@ let generateMultiSpec = async (~baseSpec: openAPISpec, ~forkSpecs: array<forkSpe
179
183
  }
180
184
 
181
185
  // Compare two specs and generate diff report
186
+ @genType
182
187
  let compareSpecs = async (~baseSpec, ~forkSpec, ~baseName="base", ~forkName="fork", ~outputPath=?) => {
183
188
  let diff = SpecDiffer.generateDiff(~baseSpec, ~forkSpec, ~baseEndpoints=OpenAPIParser.getAllEndpoints(baseSpec), ~forkEndpoints=OpenAPIParser.getAllEndpoints(forkSpec))
184
189
  outputPath->Option.forEach(path => {
@@ -188,6 +193,7 @@ let compareSpecs = async (~baseSpec, ~forkSpec, ~baseName="base", ~forkName="for
188
193
  }
189
194
 
190
195
  // Main generation function
196
+ @genType
191
197
  let generate = async (config: generationConfig): generationResult => {
192
198
  switch await SchemaRefResolver.resolve(config.specPath) {
193
199
  | Result.Error(message) => Result.Error(SpecResolutionError({url: config.specPath, message}))
@@ -207,6 +213,7 @@ let generate = async (config: generationConfig): generationResult => {
207
213
  }
208
214
  }
209
215
 
216
+ @genType
210
217
  let createDefaultConfig = (url, outputDir): generationConfig => ({
211
218
  specPath: url, outputDir, strategy: SharedBase, includeTags: None, excludeTags: None,
212
219
  modulePerTag: true, generateDiffReport: true, breakingChangeHandling: Warn,
@@ -215,8 +222,10 @@ let createDefaultConfig = (url, outputDir): generationConfig => ({
215
222
  baseInstanceName: None, baseModulePrefix: None,
216
223
  })
217
224
 
225
+ @genType
218
226
  let generateFromUrl = async (~url, ~outputDir, ~config=?) =>
219
227
  await generate({...config->Option.getOr(createDefaultConfig(url, outputDir)), specPath: url})
220
228
 
229
+ @genType
221
230
  let generateFromFile = async (~filePath, ~outputDir, ~config=?) =>
222
231
  await generate({...config->Option.getOr(createDefaultConfig(filePath, outputDir)), specPath: filePath})
package/src/Types.res CHANGED
@@ -3,6 +3,7 @@
3
3
  // Types.res - Core OpenAPI and generation types (refactored & compact)
4
4
 
5
5
  // ============= JSON Schema Types =============
6
+ @genType
6
7
  type rec jsonSchemaType =
7
8
  | String
8
9
  | Number
@@ -13,6 +14,7 @@ type rec jsonSchemaType =
13
14
  | Null
14
15
  | Unknown
15
16
 
17
+ @genType
16
18
  and jsonSchema = {
17
19
  @as("type") type_: option<jsonSchemaType>,
18
20
  properties: option<dict<jsonSchema>>,
@@ -34,25 +36,30 @@ and jsonSchema = {
34
36
  }
35
37
 
36
38
  // ============= OpenAPI 3.1 Types =============
39
+ @genType
37
40
  type httpMethod = [#GET | #POST | #PUT | #PATCH | #DELETE | #HEAD | #OPTIONS]
38
41
 
42
+ @genType
39
43
  type mediaType = {
40
44
  schema: option<jsonSchema>,
41
45
  example: option<JSON.t>,
42
46
  examples: option<dict<JSON.t>>,
43
47
  }
44
48
 
49
+ @genType
45
50
  type requestBody = {
46
51
  description: option<string>,
47
52
  content: dict<mediaType>,
48
53
  required: option<bool>,
49
54
  }
50
55
 
56
+ @genType
51
57
  type response = {
52
58
  description: string,
53
59
  content: option<dict<mediaType>>,
54
60
  }
55
61
 
62
+ @genType
56
63
  type parameter = {
57
64
  name: string,
58
65
  @as("in") in_: string,
@@ -61,6 +68,7 @@ type parameter = {
61
68
  schema: option<jsonSchema>,
62
69
  }
63
70
 
71
+ @genType
64
72
  type operation = {
65
73
  operationId: option<string>,
66
74
  summary: option<string>,
@@ -71,6 +79,7 @@ type operation = {
71
79
  parameters: option<array<parameter>>,
72
80
  }
73
81
 
82
+ @genType
74
83
  type endpoint = {
75
84
  path: string,
76
85
  method: string,
@@ -83,6 +92,7 @@ type endpoint = {
83
92
  parameters: option<array<parameter>>,
84
93
  }
85
94
 
95
+ @genType
86
96
  type pathItem = {
87
97
  get: option<operation>,
88
98
  post: option<operation>,
@@ -94,14 +104,17 @@ type pathItem = {
94
104
  parameters: option<array<parameter>>,
95
105
  }
96
106
 
107
+ @genType
97
108
  type components = {schemas: option<dict<jsonSchema>>}
98
109
 
110
+ @genType
99
111
  type info = {
100
112
  title: string,
101
113
  version: string,
102
114
  description: option<string>,
103
115
  }
104
116
 
117
+ @genType
105
118
  type openAPISpec = {
106
119
  openapi: string,
107
120
  info: info,
@@ -111,32 +124,40 @@ type openAPISpec = {
111
124
 
112
125
  // ============= Re-exports from focused modules =============
113
126
  // Config types
127
+ @genType
114
128
  type generationStrategy = Config.generationStrategy =
115
129
  | Separate
116
130
  | SharedBase
117
131
 
132
+ @genType
118
133
  type breakingChangeHandling = Config.breakingChangeHandling = | Error | Warn | Ignore
134
+ @genType
119
135
  type forkSpecConfig = Config.forkSpecConfig = {name: string, specPath: string}
136
+ @genType
120
137
  type generationTargets = Config.generationTargets = {
121
138
  rescriptApi: bool,
122
139
  rescriptWrapper: bool,
123
140
  typescriptDts: bool,
124
141
  typescriptWrapper: bool,
125
142
  }
143
+ @genType
126
144
  type generationConfig = Config.t
127
145
 
146
+ @genType
128
147
  type forkSpec = {
129
148
  name: string,
130
149
  spec: openAPISpec,
131
150
  }
132
151
 
133
152
  // Error types - use `=` syntax to re-export constructors
153
+ @genType
134
154
  type errorContext = CodegenError.context = {
135
155
  path: string,
136
156
  operation: string,
137
157
  schema: option<JSON.t>,
138
158
  }
139
159
 
160
+ @genType
140
161
  type codegenError = CodegenError.t =
141
162
  | SpecResolutionError({url: string, message: string})
142
163
  | SchemaParseError({context: errorContext, reason: string})
@@ -147,6 +168,7 @@ type codegenError = CodegenError.t =
147
168
  | InvalidConfigError({field: string, message: string})
148
169
  | UnknownError({message: string, context: option<errorContext>})
149
170
 
171
+ @genType
150
172
  type warning = CodegenError.Warning.t =
151
173
  | FallbackToJson({reason: string, context: errorContext})
152
174
  | UnsupportedFeature({feature: string, fallback: string, location: string})
@@ -156,6 +178,7 @@ type warning = CodegenError.Warning.t =
156
178
  | ComplexUnionSimplified({location: string, types: string})
157
179
 
158
180
  // ============= Diff Types =============
181
+ @genType
159
182
  type endpointDiff = {
160
183
  path: string,
161
184
  method: string,
@@ -164,11 +187,13 @@ type endpointDiff = {
164
187
  breakingChange: bool,
165
188
  }
166
189
 
190
+ @genType
167
191
  type schemaDiff = {
168
192
  name: string,
169
193
  breakingChange: bool,
170
194
  }
171
195
 
196
+ @genType
172
197
  type specDiff = {
173
198
  addedEndpoints: array<endpoint>,
174
199
  removedEndpoints: array<endpoint>,
@@ -179,12 +204,14 @@ type specDiff = {
179
204
  }
180
205
 
181
206
  // ============= Generation Result Types =============
207
+ @genType
182
208
  type generationSuccess = {
183
209
  generatedFiles: array<string>,
184
210
  diff: option<specDiff>,
185
211
  warnings: array<warning>,
186
212
  }
187
213
 
214
+ @genType
188
215
  type generationResult = result<generationSuccess, codegenError>
189
216
 
190
217
  // ============= Re-export helper modules =============
@@ -8,6 +8,7 @@
8
8
  @module("pathe") external dirname: string => string = "dirname"
9
9
 
10
10
  // Represents a file to be written
11
+ @genType
11
12
  type fileToWrite = {
12
13
  path: string,
13
14
  content: string,
@@ -3,6 +3,7 @@
3
3
  // Pipeline.res - Compact data transformation pipeline
4
4
  open Types
5
5
 
6
+ @genType
6
7
  type t = {
7
8
  files: array<FileSystem.fileToWrite>,
8
9
  warnings: array<warning>,