@f3liz/rescript-autogen-openapi 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -9,12 +9,25 @@ Generate ReScript code with [Sury](https://github.com/DZakh/rescript-schema) sch
9
9
  * **Multi-Fork Support**: Intelligently handles multiple API forks (like Misskey, Cherrypick, Firefish) by extracting shared code and generating fork-specific extensions.
10
10
  * **Unified IR Pipeline**: Advanced type inference with a unified intermediate representation that generates both types and schemas.
11
11
  * **Diff & Merge**: Compare specs, generate diff reports, and optimize code reuse across variants.
12
- * **TypeScript Support**: Generates `.d.ts` files and TypeScript wrappers for idiomatic use in JS/TS projects.
12
+ * **TypeScript Support**: First-class TypeScript support via `genType`. Exported functions and types are idiomatic and fully typed for use in TypeScript projects.
13
13
 
14
14
  ## 📦 Installation
15
15
 
16
16
  ```bash
17
- npm install @f3liz/rescript-autogen-openapi sury @readme/openapi-parser
17
+ npm install @f3liz/rescript-autogen-openapi sury
18
+ ```
19
+
20
+ **Important**: This library has a peer dependency on `sury` (ReScript Schema). You must install it in your project because the generated code directly depends on it for runtime validation.
21
+
22
+ ### Configure `rescript.json`
23
+
24
+ Add `sury` to your project dependencies:
25
+
26
+ ```json
27
+ {
28
+ "name": "my-project",
29
+ "dependencies": ["sury"]
30
+ }
18
31
  ```
19
32
 
20
33
  Ensure you have `rescript` (^12.0.0) installed.
@@ -0,0 +1,28 @@
1
+ import type { codegenError as Types_codegenError } from './Types';
2
+ import type { forkSpec as Types_forkSpec } from './Types';
3
+ import type { generationConfig as Types_generationConfig } from './Types';
4
+ import type { generationResult as Types_generationResult } from './Types';
5
+ import type { openAPISpec as Types_openAPISpec } from './Types';
6
+ import type { specDiff as Types_specDiff } from './Types';
7
+ import type { t as Pipeline_t } from './core/Pipeline';
8
+ export declare const generateSingleSpecPure: (spec: Types_openAPISpec, config: Types_generationConfig) => {
9
+ TAG: "Ok";
10
+ _0: Pipeline_t;
11
+ } | {
12
+ TAG: "Error";
13
+ _0: Types_codegenError;
14
+ };
15
+ export declare const generateSingleSpec: (spec: Types_openAPISpec, config: Types_generationConfig) => Promise<Types_generationResult>;
16
+ export declare const generateMultiSpecPure: (baseSpec: Types_openAPISpec, forkSpecs: Types_forkSpec[], config: Types_generationConfig) => {
17
+ TAG: "Ok";
18
+ _0: Pipeline_t;
19
+ } | {
20
+ TAG: "Error";
21
+ _0: Types_codegenError;
22
+ };
23
+ export declare const generateMultiSpec: (baseSpec: Types_openAPISpec, forkSpecs: Types_forkSpec[], config: Types_generationConfig) => Promise<Types_generationResult>;
24
+ export declare const compareSpecs: (baseSpec: Types_openAPISpec, forkSpec: Types_openAPISpec, baseName: (undefined | string), forkName: (undefined | string), outputPath: (undefined | string)) => Promise<Types_specDiff>;
25
+ export declare const generate: (config: Types_generationConfig) => Promise<Types_generationResult>;
26
+ export declare const createDefaultConfig: (url: string, outputDir: string) => Types_generationConfig;
27
+ export declare const generateFromUrl: (url: string, outputDir: string, config: (undefined | Types_generationConfig)) => Promise<Types_generationResult>;
28
+ export declare const generateFromFile: (filePath: string, outputDir: string, config: (undefined | Types_generationConfig)) => Promise<Types_generationResult>;
@@ -0,0 +1,286 @@
1
+ import type { t as Config_t } from './types/Config';
2
+ export type jsonSchemaType = "String" | "Number" | "Integer" | "Boolean" | "Object" | "Null" | "Unknown" | {
3
+ TAG: "Array";
4
+ _0: jsonSchemaType;
5
+ };
6
+ export type jsonSchema = {
7
+ readonly type: (undefined | jsonSchemaType);
8
+ readonly properties: (undefined | {
9
+ [id: string]: jsonSchema;
10
+ });
11
+ readonly items: (undefined | jsonSchema);
12
+ readonly required: (undefined | string[]);
13
+ readonly enum: (undefined | unknown[]);
14
+ readonly "$ref": (undefined | string);
15
+ readonly allOf: (undefined | jsonSchema[]);
16
+ readonly oneOf: (undefined | jsonSchema[]);
17
+ readonly anyOf: (undefined | jsonSchema[]);
18
+ readonly description: (undefined | string);
19
+ readonly format: (undefined | string);
20
+ readonly minLength: (undefined | number);
21
+ readonly maxLength: (undefined | number);
22
+ readonly minimum: (undefined | number);
23
+ readonly maximum: (undefined | number);
24
+ readonly pattern: (undefined | string);
25
+ readonly nullable: (undefined | boolean);
26
+ };
27
+ export type httpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
28
+ export type mediaType = {
29
+ readonly schema: (undefined | jsonSchema);
30
+ readonly example: (undefined | unknown);
31
+ readonly examples: (undefined | {
32
+ [id: string]: unknown;
33
+ });
34
+ };
35
+ export type requestBody = {
36
+ readonly description: (undefined | string);
37
+ readonly content: {
38
+ [id: string]: mediaType;
39
+ };
40
+ readonly required: (undefined | boolean);
41
+ };
42
+ export type response = {
43
+ readonly description: string;
44
+ readonly content: (undefined | {
45
+ [id: string]: mediaType;
46
+ });
47
+ };
48
+ export type parameter = {
49
+ readonly name: string;
50
+ readonly in: string;
51
+ readonly description: (undefined | string);
52
+ readonly required: (undefined | boolean);
53
+ readonly schema: (undefined | jsonSchema);
54
+ };
55
+ export type operation = {
56
+ readonly operationId: (undefined | string);
57
+ readonly summary: (undefined | string);
58
+ readonly description: (undefined | string);
59
+ readonly tags: (undefined | string[]);
60
+ readonly requestBody: (undefined | requestBody);
61
+ readonly responses: {
62
+ [id: string]: response;
63
+ };
64
+ readonly parameters: (undefined | parameter[]);
65
+ };
66
+ export type endpoint = {
67
+ readonly path: string;
68
+ readonly method: string;
69
+ readonly operationId: (undefined | string);
70
+ readonly summary: (undefined | string);
71
+ readonly description: (undefined | string);
72
+ readonly tags: (undefined | string[]);
73
+ readonly requestBody: (undefined | requestBody);
74
+ readonly responses: {
75
+ [id: string]: response;
76
+ };
77
+ readonly parameters: (undefined | parameter[]);
78
+ };
79
+ export type pathItem = {
80
+ readonly get: (undefined | operation);
81
+ readonly post: (undefined | operation);
82
+ readonly put: (undefined | operation);
83
+ readonly patch: (undefined | operation);
84
+ readonly delete: (undefined | operation);
85
+ readonly head: (undefined | operation);
86
+ readonly options: (undefined | operation);
87
+ readonly parameters: (undefined | parameter[]);
88
+ };
89
+ export type components = {
90
+ readonly schemas: (undefined | {
91
+ [id: string]: jsonSchema;
92
+ });
93
+ };
94
+ export type info = {
95
+ readonly title: string;
96
+ readonly version: string;
97
+ readonly description: (undefined | string);
98
+ };
99
+ export type openAPISpec = {
100
+ readonly openapi: string;
101
+ readonly info: info;
102
+ readonly paths: {
103
+ [id: string]: pathItem;
104
+ };
105
+ readonly components: (undefined | components);
106
+ };
107
+ export type generationStrategy = "Separate" | "SharedBase";
108
+ export type breakingChangeHandling = "Error" | "Warn" | "Ignore";
109
+ export type forkSpecConfig = {
110
+ readonly name: string;
111
+ readonly specPath: string;
112
+ };
113
+ export type generationTargets = {
114
+ readonly rescriptApi: boolean;
115
+ readonly rescriptWrapper: boolean;
116
+ readonly typescriptDts: boolean;
117
+ readonly typescriptWrapper: boolean;
118
+ };
119
+ export type generationConfig = Config_t;
120
+ export type forkSpec = {
121
+ readonly name: string;
122
+ readonly spec: openAPISpec;
123
+ };
124
+ export type errorContext = {
125
+ readonly path: string;
126
+ readonly operation: string;
127
+ readonly schema: (undefined | unknown);
128
+ };
129
+ export type codegenError = {
130
+ TAG: "SpecResolutionError";
131
+ readonly url: string;
132
+ readonly message: string;
133
+ } | {
134
+ TAG: "SchemaParseError";
135
+ readonly context: errorContext;
136
+ readonly reason: string;
137
+ } | {
138
+ TAG: "ReferenceError";
139
+ readonly ref: string;
140
+ readonly context: errorContext;
141
+ } | {
142
+ TAG: "ValidationError";
143
+ readonly schema: string;
144
+ readonly input: unknown;
145
+ readonly issues: string[];
146
+ } | {
147
+ TAG: "CircularSchemaError";
148
+ readonly ref: string;
149
+ readonly depth: number;
150
+ readonly path: string;
151
+ } | {
152
+ TAG: "FileWriteError";
153
+ readonly filePath: string;
154
+ readonly message: string;
155
+ } | {
156
+ TAG: "InvalidConfigError";
157
+ readonly field: string;
158
+ readonly message: string;
159
+ } | {
160
+ TAG: "UnknownError";
161
+ readonly message: string;
162
+ readonly context: (undefined | errorContext);
163
+ };
164
+ export type warning = {
165
+ TAG: "FallbackToJson";
166
+ readonly reason: string;
167
+ readonly context: errorContext;
168
+ } | {
169
+ TAG: "UnsupportedFeature";
170
+ readonly feature: string;
171
+ readonly fallback: string;
172
+ readonly location: string;
173
+ } | {
174
+ TAG: "DepthLimitReached";
175
+ readonly depth: number;
176
+ readonly path: string;
177
+ } | {
178
+ TAG: "MissingSchema";
179
+ readonly ref: string;
180
+ readonly location: string;
181
+ } | {
182
+ TAG: "IntersectionNotFullySupported";
183
+ readonly location: string;
184
+ readonly note: string;
185
+ } | {
186
+ TAG: "ComplexUnionSimplified";
187
+ readonly location: string;
188
+ readonly types: string;
189
+ };
190
+ export type endpointDiff = {
191
+ readonly path: string;
192
+ readonly method: string;
193
+ readonly requestBodyChanged: boolean;
194
+ readonly responseChanged: boolean;
195
+ readonly breakingChange: boolean;
196
+ };
197
+ export type schemaDiff = {
198
+ readonly name: string;
199
+ readonly breakingChange: boolean;
200
+ };
201
+ export type specDiff = {
202
+ readonly addedEndpoints: endpoint[];
203
+ readonly removedEndpoints: endpoint[];
204
+ readonly modifiedEndpoints: endpointDiff[];
205
+ readonly addedSchemas: string[];
206
+ readonly removedSchemas: string[];
207
+ readonly modifiedSchemas: schemaDiff[];
208
+ };
209
+ export type generationSuccess = {
210
+ readonly generatedFiles: string[];
211
+ readonly diff: (undefined | specDiff);
212
+ readonly warnings: warning[];
213
+ };
214
+ export type generationResult = {
215
+ TAG: "Ok";
216
+ _0: generationSuccess;
217
+ } | {
218
+ TAG: "Error";
219
+ _0: codegenError;
220
+ };
221
+ export type CodegenError_context = {
222
+ readonly path: string;
223
+ readonly operation: string;
224
+ readonly schema: (undefined | unknown);
225
+ };
226
+ export type CodegenError_t = {
227
+ TAG: "SpecResolutionError";
228
+ readonly url: string;
229
+ readonly message: string;
230
+ } | {
231
+ TAG: "SchemaParseError";
232
+ readonly context: CodegenError_context;
233
+ readonly reason: string;
234
+ } | {
235
+ TAG: "ReferenceError";
236
+ readonly ref: string;
237
+ readonly context: CodegenError_context;
238
+ } | {
239
+ TAG: "ValidationError";
240
+ readonly schema: string;
241
+ readonly input: unknown;
242
+ readonly issues: string[];
243
+ } | {
244
+ TAG: "CircularSchemaError";
245
+ readonly ref: string;
246
+ readonly depth: number;
247
+ readonly path: string;
248
+ } | {
249
+ TAG: "FileWriteError";
250
+ readonly filePath: string;
251
+ readonly message: string;
252
+ } | {
253
+ TAG: "InvalidConfigError";
254
+ readonly field: string;
255
+ readonly message: string;
256
+ } | {
257
+ TAG: "UnknownError";
258
+ readonly message: string;
259
+ readonly context: (undefined | CodegenError_context);
260
+ };
261
+ export type Warning_t = {
262
+ TAG: "FallbackToJson";
263
+ readonly reason: string;
264
+ readonly context: CodegenError_context;
265
+ } | {
266
+ TAG: "UnsupportedFeature";
267
+ readonly feature: string;
268
+ readonly fallback: string;
269
+ readonly location: string;
270
+ } | {
271
+ TAG: "DepthLimitReached";
272
+ readonly depth: number;
273
+ readonly path: string;
274
+ } | {
275
+ TAG: "MissingSchema";
276
+ readonly ref: string;
277
+ readonly location: string;
278
+ } | {
279
+ TAG: "IntersectionNotFullySupported";
280
+ readonly location: string;
281
+ readonly note: string;
282
+ } | {
283
+ TAG: "ComplexUnionSimplified";
284
+ readonly location: string;
285
+ readonly types: string;
286
+ };
@@ -0,0 +1,4 @@
1
+ export type fileToWrite = {
2
+ readonly path: string;
3
+ readonly content: string;
4
+ };
@@ -0,0 +1,6 @@
1
+ import type { fileToWrite as FileSystem_fileToWrite } from './FileSystem';
2
+ import type { warning as Types_warning } from '../../src/Types';
3
+ export type t = {
4
+ readonly files: FileSystem_fileToWrite[];
5
+ readonly warnings: Types_warning[];
6
+ };
@@ -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.1.7",
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,26 @@
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
32
  "test": "node --test"
32
33
  },
33
34
  "main": "lib/es6/src/Codegen.mjs",
35
+ "types": "lib/es6/src/Codegen.d.ts",
34
36
  "type": "module",
35
37
  "dependencies": {
36
38
  "@readme/openapi-parser": "^5.5.0",
37
39
  "js-convert-case": "^4.2.0",
38
- "pathe": "^2.0.3",
39
- "sury": "11.0.0-alpha.4"
40
+ "pathe": "^2.0.3"
40
41
  },
41
42
  "devDependencies": {
42
- "rescript": "^12.1.0"
43
+ "rescript": "^12.1.0",
44
+ "sury": "11.0.0-alpha.4",
45
+ "typescript": "^5.9.3"
43
46
  },
44
47
  "peerDependencies": {
45
- "rescript": "^12.0.0"
48
+ "rescript": "^12.0.0",
49
+ "sury": ">=11.0.0-alpha.4"
46
50
  }
47
51
  }
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>,
@@ -3,6 +3,7 @@
3
3
  // Error.res - Compact error and warning types with helpers
4
4
 
5
5
  // Error context for debugging (defined here to avoid circular dependency)
6
+ @genType
6
7
  type context = {
7
8
  path: string,
8
9
  operation: string,
@@ -10,6 +11,7 @@ type context = {
10
11
  }
11
12
 
12
13
  // Structured error types (keep original names for backward compat)
14
+ @genType
13
15
  type t =
14
16
  | SpecResolutionError({url: string, message: string})
15
17
  | SchemaParseError({context: context, reason: string})
@@ -22,6 +24,7 @@ type t =
22
24
 
23
25
  // Warning types
24
26
  module Warning = {
27
+ @genType
25
28
  type t =
26
29
  | FallbackToJson({reason: string, context: context})
27
30
  | UnsupportedFeature({feature: string, fallback: string, location: string})
@@ -2,20 +2,24 @@
2
2
 
3
3
  // Config.res - Generation configuration types
4
4
 
5
+ @genType
5
6
  type generationStrategy =
6
7
  | Separate
7
8
  | SharedBase
8
9
 
10
+ @genType
9
11
  type breakingChangeHandling =
10
12
  | Error
11
13
  | Warn
12
14
  | Ignore
13
15
 
16
+ @genType
14
17
  type forkSpecConfig = {
15
18
  name: string,
16
19
  specPath: string,
17
20
  }
18
21
 
22
+ @genType
19
23
  type generationTargets = {
20
24
  rescriptApi: bool, // Generate base ReScript API (always true by default)
21
25
  rescriptWrapper: bool, // Generate ReScript thin wrapper (pipe-first)
@@ -23,6 +27,7 @@ type generationTargets = {
23
27
  typescriptWrapper: bool, // Generate TypeScript/JavaScript wrapper
24
28
  }
25
29
 
30
+ @genType
26
31
  type t = {
27
32
  specPath: string,
28
33
  forkSpecs: option<array<forkSpecConfig>>,
@@ -43,6 +48,7 @@ type t = {
43
48
  }
44
49
 
45
50
  // Default configuration
51
+ @genType
46
52
  let make = (
47
53
  ~specPath,
48
54
  ~outputDir,