@f3liz/rescript-autogen-openapi 0.1.5 → 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 +15 -2
- package/lib/es6/src/Codegen.d.ts +28 -0
- package/lib/es6/src/Codegen.mjs +8 -8
- package/lib/es6/src/Types.d.ts +286 -0
- package/lib/es6/src/core/CodegenUtils.mjs +5 -5
- package/lib/es6/src/core/DocOverride.mjs +2 -2
- package/lib/es6/src/core/FileSystem.d.ts +4 -0
- package/lib/es6/src/core/FileSystem.mjs +3 -3
- package/lib/es6/src/core/Pipeline.d.ts +6 -0
- package/lib/es6/src/core/ReferenceResolver.mjs +4 -4
- package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +3 -3
- package/lib/es6/src/generators/EndpointGenerator.mjs +3 -3
- package/lib/es6/src/generators/IRToSuryGenerator.mjs +4 -4
- package/lib/es6/src/generators/IRToTypeGenerator.mjs +5 -5
- package/lib/es6/src/generators/IRToTypeScriptGenerator.mjs +3 -3
- package/lib/es6/src/generators/ModuleGenerator.mjs +9 -9
- package/lib/es6/src/generators/SchemaCodeGenerator.mjs +4 -4
- package/lib/es6/src/generators/ThinWrapperGenerator.mjs +2 -2
- package/lib/es6/src/generators/TypeScriptDtsGenerator.mjs +7 -7
- package/lib/es6/src/generators/TypeScriptWrapperGenerator.mjs +7 -7
- package/lib/es6/src/types/CodegenError.d.ts +66 -0
- package/lib/es6/src/types/Config.d.ts +31 -0
- package/package.json +12 -8
- package/rescript.json +6 -0
- package/src/Codegen.res +9 -0
- package/src/Types.res +27 -0
- package/src/core/CodegenUtils.res +2 -2
- package/src/core/FileSystem.res +3 -2
- package/src/core/Pipeline.res +1 -0
- package/src/types/CodegenError.res +3 -0
- package/src/types/Config.res +6 -0
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**:
|
|
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
|
|
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>;
|
package/lib/es6/src/Codegen.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Config from "./types/Config.mjs";
|
|
4
4
|
import * as Pipeline from "./core/Pipeline.mjs";
|
|
5
|
-
import * as Text from "@std/text";
|
|
6
5
|
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
7
6
|
import * as FileSystem from "./core/FileSystem.mjs";
|
|
8
7
|
import * as SpecDiffer from "./core/SpecDiffer.mjs";
|
|
@@ -14,6 +13,7 @@ import * as OpenAPIParser from "./core/OpenAPIParser.mjs";
|
|
|
14
13
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
15
14
|
import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
|
|
16
15
|
import * as ModuleGenerator from "./generators/ModuleGenerator.mjs";
|
|
16
|
+
import * as JsConvertCase from "js-convert-case";
|
|
17
17
|
import * as SchemaRefResolver from "./core/SchemaRefResolver.mjs";
|
|
18
18
|
import * as DiffReportGenerator from "./generators/DiffReportGenerator.mjs";
|
|
19
19
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
@@ -32,7 +32,7 @@ function generateSingleSpecPure(spec, config) {
|
|
|
32
32
|
ComponentSchemaGenerator.generate(spec, config.outputDir),
|
|
33
33
|
config.modulePerTag ? ModuleGenerator.generateTagModuleFiles(endpoints, config.outputDir, undefined, config.docOverrideDir) : ModuleGenerator.generateFlatModuleFile("API", endpoints, config.outputDir, config.docOverrideDir)
|
|
34
34
|
]) : Pipeline.empty;
|
|
35
|
-
let wrapperOutput = targets.rescriptWrapper ? ThinWrapperGenerator.generateWrapper(spec, endpoints, undefined, config.outputDir,
|
|
35
|
+
let wrapperOutput = targets.rescriptWrapper ? ThinWrapperGenerator.generateWrapper(spec, endpoints, undefined, config.outputDir, JsConvertCase.toPascalCase(spec.info.title) + "Wrapper", "", undefined) : Pipeline.empty;
|
|
36
36
|
let dtsOutput = targets.typescriptDts ? TypeScriptDtsGenerator.generate(spec, endpoints, Stdlib_Option.getOr(config.dtsOutputDir, config.outputDir)) : Pipeline.empty;
|
|
37
37
|
let tsWrapperOutput = targets.typescriptWrapper ? TypeScriptWrapperGenerator.generate(endpoints, Stdlib_Option.getOr(config.wrapperOutputDir, config.outputDir), "../generated") : Pipeline.empty;
|
|
38
38
|
return {
|
|
@@ -136,11 +136,11 @@ function processForkPure(baseSpec, baseEndpoints, fork, config) {
|
|
|
136
136
|
if (match$1 === "Separate") {
|
|
137
137
|
codeOutput = Pipeline.fromFile({
|
|
138
138
|
path: FileSystem.makePath(config.outputDir, fork.name + `.res`),
|
|
139
|
-
content: ModuleGenerator.generateFlatModuleCode(
|
|
139
|
+
content: ModuleGenerator.generateFlatModuleCode(JsConvertCase.toPascalCase(fork.name), forkEndpoints, config.docOverrideDir)
|
|
140
140
|
});
|
|
141
141
|
} else {
|
|
142
142
|
let baseName = Stdlib_Option.getOrThrow(config.baseInstanceName, "baseInstanceName required");
|
|
143
|
-
let basePrefix = Stdlib_Option.getOr(config.baseModulePrefix,
|
|
143
|
+
let basePrefix = Stdlib_Option.getOr(config.baseModulePrefix, JsConvertCase.toPascalCase(baseName));
|
|
144
144
|
codeOutput = ModuleGenerator.generateSeparatePerTagModules(baseName, basePrefix, fork.name, undefined, sharedEndpoints, extensionEndpoints, Stdlib_Option.flatMap(sharedSpec.components, c => c.schemas), Stdlib_Option.flatMap(fork.spec.components, c => c.schemas), config.outputDir, config.docOverrideDir);
|
|
145
145
|
}
|
|
146
146
|
let targets = Stdlib_Option.getOr(config.targets, {
|
|
@@ -160,12 +160,12 @@ function processForkPure(baseSpec, baseEndpoints, fork, config) {
|
|
|
160
160
|
sharedSpec,
|
|
161
161
|
sharedEndpoints,
|
|
162
162
|
extensionEndpoints,
|
|
163
|
-
Stdlib_Option.getOr(config.baseModulePrefix, Stdlib_Option.getOr(Stdlib_Option.map(config.baseInstanceName, prim =>
|
|
163
|
+
Stdlib_Option.getOr(config.baseModulePrefix, Stdlib_Option.getOr(Stdlib_Option.map(config.baseInstanceName, prim => JsConvertCase.toPascalCase(prim)), ""))
|
|
164
164
|
];
|
|
165
165
|
let wExt = match$3[2];
|
|
166
166
|
let wShared = match$3[1];
|
|
167
167
|
let wSpec = match$3[0];
|
|
168
|
-
let wrapperOutput = targets.rescriptWrapper ? ThinWrapperGenerator.generateWrapper(wSpec, wShared, wExt, FileSystem.makePath(config.outputDir, fork.name),
|
|
168
|
+
let wrapperOutput = targets.rescriptWrapper ? ThinWrapperGenerator.generateWrapper(wSpec, wShared, wExt, FileSystem.makePath(config.outputDir, fork.name), JsConvertCase.toPascalCase(fork.name) + "Wrapper", JsConvertCase.toPascalCase(fork.name), match$3[3]) : Pipeline.empty;
|
|
169
169
|
let allWEndpoints = wShared.concat(wExt);
|
|
170
170
|
let dtsOutput = targets.typescriptDts ? TypeScriptDtsGenerator.generate(wSpec, allWEndpoints, FileSystem.makePath(Stdlib_Option.getOr(config.dtsOutputDir, config.outputDir), fork.name)) : Pipeline.empty;
|
|
171
171
|
let tsWrapperOutput = targets.typescriptWrapper ? TypeScriptWrapperGenerator.generate(allWEndpoints, FileSystem.makePath(Stdlib_Option.getOr(config.wrapperOutputDir, config.outputDir), fork.name), `../../generated/` + fork.name) : Pipeline.empty;
|
|
@@ -232,7 +232,7 @@ function generateMultiSpecPure(baseSpec, forkSpecs, config) {
|
|
|
232
232
|
});
|
|
233
233
|
let targets = Stdlib_Option.getOr(config.targets, Config.defaultTargets());
|
|
234
234
|
let baseName = Stdlib_Option.getOrThrow(config.baseInstanceName, "baseInstanceName required");
|
|
235
|
-
let basePrefix = Stdlib_Option.getOr(config.baseModulePrefix,
|
|
235
|
+
let basePrefix = Stdlib_Option.getOr(config.baseModulePrefix, JsConvertCase.toPascalCase(baseName));
|
|
236
236
|
let baseOutputDir = FileSystem.makePath(config.outputDir, baseName);
|
|
237
237
|
let baseWrappers = Pipeline.combine([
|
|
238
238
|
targets.rescriptWrapper ? ThinWrapperGenerator.generateWrapper(baseSpec, baseEndpoints, undefined, baseOutputDir, basePrefix + "Wrapper", basePrefix, undefined) : Pipeline.empty,
|
|
@@ -420,4 +420,4 @@ export {
|
|
|
420
420
|
generateFromUrl,
|
|
421
421
|
generateFromFile,
|
|
422
422
|
}
|
|
423
|
-
/*
|
|
423
|
+
/* FileSystem Not a pure module */
|
|
@@ -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
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Text from "@std/text";
|
|
4
3
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
import * as JsConvertCase from "js-convert-case";
|
|
5
5
|
|
|
6
6
|
function sanitizeIdentifier(str) {
|
|
7
7
|
return str.replaceAll("{", "").replaceAll("}", "").replaceAll("[", "").replaceAll("]", "").replaceAll(".", "_").replaceAll("-", "_").replaceAll("/", "_").replaceAll(" ", "_");
|
|
@@ -9,13 +9,13 @@ function sanitizeIdentifier(str) {
|
|
|
9
9
|
|
|
10
10
|
function generateTypeName(prefixOpt, path, suffix) {
|
|
11
11
|
let prefix = prefixOpt !== undefined ? prefixOpt : "";
|
|
12
|
-
let cleaned = sanitizeIdentifier(path.replaceAll("/", "_")).split("_").filter(part => part !== "").map(prim =>
|
|
12
|
+
let cleaned = sanitizeIdentifier(path.replaceAll("/", "_")).split("_").filter(part => part !== "").map(prim => JsConvertCase.toPascalCase(prim)).join("");
|
|
13
13
|
return prefix + cleaned + suffix;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function generateOperationName(operationId, path, method) {
|
|
17
17
|
if (operationId !== undefined) {
|
|
18
|
-
return
|
|
18
|
+
return JsConvertCase.toCamelCase(sanitizeIdentifier(operationId));
|
|
19
19
|
} else {
|
|
20
20
|
return method.toLowerCase() + path.split("/").filter(part => {
|
|
21
21
|
if (part !== "") {
|
|
@@ -23,7 +23,7 @@ function generateOperationName(operationId, path, method) {
|
|
|
23
23
|
} else {
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
|
-
}).map(prim =>
|
|
26
|
+
}).map(prim => JsConvertCase.toCamelCase(prim)).join("");
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -183,4 +183,4 @@ export {
|
|
|
183
183
|
generateDocString,
|
|
184
184
|
fetchTypeSignature,
|
|
185
185
|
}
|
|
186
|
-
/*
|
|
186
|
+
/* js-convert-case Not a pure module */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Fs from "fs";
|
|
4
|
-
import * as Text from "@std/text";
|
|
5
4
|
import * as Js_string from "@rescript/runtime/lib/es6/Js_string.js";
|
|
6
5
|
import * as FileSystem from "./FileSystem.mjs";
|
|
7
6
|
import * as CodegenUtils from "./CodegenUtils.mjs";
|
|
8
7
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
9
8
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
10
9
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
|
+
import * as JsConvertCase from "js-convert-case";
|
|
11
11
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
12
12
|
|
|
13
13
|
function generateEndpointHash(endpoint) {
|
|
@@ -264,7 +264,7 @@ function generateOverrideFiles(spec, endpoints, outputDir, host, groupByTagOpt,
|
|
|
264
264
|
moduleName = "API";
|
|
265
265
|
}
|
|
266
266
|
let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
|
|
267
|
-
let modulePath = FileSystem.makePath(outputDir,
|
|
267
|
+
let modulePath = FileSystem.makePath(outputDir, JsConvertCase.toPascalCase(moduleName));
|
|
268
268
|
let filePath = FileSystem.makePath(modulePath, functionName + ".md");
|
|
269
269
|
if (isFileCustomized(filePath)) {
|
|
270
270
|
console.log(`ℹ️ Skipping ` + moduleName + `/` + functionName + ` - file already customized`);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Fs from "fs";
|
|
4
|
-
import * as
|
|
4
|
+
import * as Pathe from "pathe";
|
|
5
5
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
6
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
7
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
8
8
|
|
|
9
9
|
function ensureDir(path) {
|
|
10
10
|
try {
|
|
11
|
-
Fs.mkdirSync(
|
|
11
|
+
Fs.mkdirSync(Pathe.dirname(path), {
|
|
12
12
|
recursive: true
|
|
13
13
|
});
|
|
14
14
|
return;
|
|
@@ -66,7 +66,7 @@ function writeFiles(files) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function makePath(baseDir, filename) {
|
|
69
|
-
return
|
|
69
|
+
return Pathe.join(baseDir, filename);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as
|
|
3
|
+
import * as JsConvertCase from "js-convert-case";
|
|
4
4
|
|
|
5
5
|
function refToTypePath(insideComponentSchemasOpt, modulePrefixOpt, ref) {
|
|
6
6
|
let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
|
|
@@ -10,7 +10,7 @@ function refToTypePath(insideComponentSchemasOpt, modulePrefixOpt, ref) {
|
|
|
10
10
|
if (schemaName === undefined) {
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
let moduleName =
|
|
13
|
+
let moduleName = JsConvertCase.toPascalCase(schemaName);
|
|
14
14
|
if (insideComponentSchemas) {
|
|
15
15
|
return moduleName + `.t`;
|
|
16
16
|
} else {
|
|
@@ -26,7 +26,7 @@ function refToSchemaPath(insideComponentSchemasOpt, modulePrefixOpt, ref) {
|
|
|
26
26
|
if (schemaName === undefined) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
let moduleName =
|
|
29
|
+
let moduleName = JsConvertCase.toPascalCase(schemaName);
|
|
30
30
|
if (insideComponentSchemas) {
|
|
31
31
|
return moduleName + `.schema`;
|
|
32
32
|
} else {
|
|
@@ -38,4 +38,4 @@ export {
|
|
|
38
38
|
refToTypePath,
|
|
39
39
|
refToSchemaPath,
|
|
40
40
|
}
|
|
41
|
-
/*
|
|
41
|
+
/* js-convert-case Not a pure module */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Pipeline from "../core/Pipeline.mjs";
|
|
4
|
-
import * as Text from "@std/text";
|
|
5
4
|
import * as FileSystem from "../core/FileSystem.mjs";
|
|
6
5
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
7
6
|
import * as CodegenUtils from "../core/CodegenUtils.mjs";
|
|
8
7
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
9
8
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
9
|
import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
|
|
10
|
+
import * as JsConvertCase from "js-convert-case";
|
|
11
11
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
12
12
|
import * as GenerationContext from "../types/GenerationContext.mjs";
|
|
13
13
|
import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
|
|
@@ -105,7 +105,7 @@ function generate(spec, outputDir) {
|
|
|
105
105
|
warnings.push(...typeCtx.warnings);
|
|
106
106
|
warnings.push(...schemaCtx.warnings);
|
|
107
107
|
let docComment = Stdlib_Option.mapOr(schema.description, "", d => CodegenUtils.generateDocString(undefined, d, undefined));
|
|
108
|
-
return docComment + `module ` +
|
|
108
|
+
return docComment + `module ` + JsConvertCase.toPascalCase(schema.name) + ` = {
|
|
109
109
|
type t = ` + typeCode + `
|
|
110
110
|
let schema = ` + schemaCode + `
|
|
111
111
|
}`;
|
|
@@ -122,4 +122,4 @@ export {
|
|
|
122
122
|
extractReferencedSchemaNames,
|
|
123
123
|
generate,
|
|
124
124
|
}
|
|
125
|
-
/*
|
|
125
|
+
/* FileSystem Not a pure module */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Text from "@std/text";
|
|
4
3
|
import * as DocOverride from "../core/DocOverride.mjs";
|
|
5
4
|
import * as CodegenUtils from "../core/CodegenUtils.mjs";
|
|
6
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
7
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
8
7
|
import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
|
|
8
|
+
import * as JsConvertCase from "js-convert-case";
|
|
9
9
|
import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
|
|
10
10
|
import * as IRToTypeGenerator from "./IRToTypeGenerator.mjs";
|
|
11
11
|
|
|
@@ -134,7 +134,7 @@ function generateEndpointModule(endpoint, modulePrefixOpt) {
|
|
|
134
134
|
return CodegenUtils.trimMargin(`
|
|
135
135
|
|` + header.trimEnd() + `
|
|
136
136
|
|
|
|
137
|
-
|module ` +
|
|
137
|
+
|module ` + JsConvertCase.toPascalCase(functionName) + ` = {
|
|
138
138
|
|` + CodegenUtils.indent(generateEndpointCode(endpoint, undefined, undefined, modulePrefix), 2) + `
|
|
139
139
|
|}
|
|
140
140
|
|`, undefined);
|
|
@@ -169,4 +169,4 @@ export {
|
|
|
169
169
|
generateEndpointsModule,
|
|
170
170
|
generateEndpointSignature,
|
|
171
171
|
}
|
|
172
|
-
/*
|
|
172
|
+
/* DocOverride Not a pure module */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as SchemaIR from "../core/SchemaIR.mjs";
|
|
4
|
-
import * as Text from "@std/text";
|
|
5
4
|
import * as CodegenUtils from "../core/CodegenUtils.mjs";
|
|
6
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
7
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
|
+
import * as JsConvertCase from "js-convert-case";
|
|
8
8
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
9
9
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
10
10
|
import * as GenerationContext from "../types/GenerationContext.mjs";
|
|
@@ -72,7 +72,7 @@ function generateSchemaWithContext(ctx, depthOpt, irType) {
|
|
|
72
72
|
let fields = properties.map(param => {
|
|
73
73
|
let name = param[0];
|
|
74
74
|
let schemaCode = recurse(param[1]);
|
|
75
|
-
let camelName = CodegenUtils.escapeKeyword(
|
|
75
|
+
let camelName = CodegenUtils.escapeKeyword(JsConvertCase.toCamelCase(name));
|
|
76
76
|
if (param[2]) {
|
|
77
77
|
return ` ` + camelName + `: s.field("` + name + `", ` + schemaCode + `),`;
|
|
78
78
|
} else {
|
|
@@ -161,7 +161,7 @@ function generateSchemaWithContext(ctx, depthOpt, irType) {
|
|
|
161
161
|
let schemaPath;
|
|
162
162
|
if (available !== undefined) {
|
|
163
163
|
let name = Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "");
|
|
164
|
-
schemaPath = available.includes(name) ?
|
|
164
|
+
schemaPath = available.includes(name) ? JsConvertCase.toPascalCase(name) + `.schema` : `ComponentSchemas.` + JsConvertCase.toPascalCase(name) + `.schema`;
|
|
165
165
|
} else {
|
|
166
166
|
schemaPath = Stdlib_Option.getOr(ReferenceResolver.refToSchemaPath(ctx.insideComponentSchemas, ctx.modulePrefix, ref), "S.json");
|
|
167
167
|
}
|
|
@@ -230,4 +230,4 @@ export {
|
|
|
230
230
|
generateNamedSchema,
|
|
231
231
|
generateAllSchemas,
|
|
232
232
|
}
|
|
233
|
-
/*
|
|
233
|
+
/* CodegenUtils Not a pure module */
|