osury 0.3.0 → 0.5.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.
- package/README.md +5 -4
- package/bin/osury.mjs +1 -1
- package/package.json +1 -1
- package/src/Codegen.res.mjs +30 -6
- package/src/Schema.gen.tsx +1 -0
- package/src/Schema.res.mjs +2 -2
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Generate ReScript types with [Sury](https://github.com/DZakh/sury) schemas from
|
|
|
11
11
|
- Automatic deduplication of identical union structures
|
|
12
12
|
- Generates `module S = Sury` alias (required by sury-ppx)
|
|
13
13
|
- Generates `Dict.gen.tsx` shim for TypeScript interop
|
|
14
|
+
- Proper JSON `null` support via `@s.nullable option<T>` PPX attribute
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
@@ -23,12 +24,12 @@ npm install -D osury
|
|
|
23
24
|
### CLI
|
|
24
25
|
|
|
25
26
|
```bash
|
|
26
|
-
# Generate to default ./Generated.res +
|
|
27
|
+
# Generate to default ./Generated.res + shims
|
|
27
28
|
npx osury openapi.json
|
|
28
29
|
|
|
29
30
|
# Generate to specific directory
|
|
30
31
|
npx osury openapi.json src/API.res
|
|
31
|
-
# Creates: src/API.res
|
|
32
|
+
# Creates: src/API.res, src/Dict.gen.tsx
|
|
32
33
|
|
|
33
34
|
# With explicit output flag
|
|
34
35
|
npx osury generate openapi.json -o src/Schema.res
|
|
@@ -78,7 +79,7 @@ type user = {
|
|
|
78
79
|
}
|
|
79
80
|
```
|
|
80
81
|
|
|
81
|
-
Also generates `Dict.gen.tsx
|
|
82
|
+
Also generates `Dict.gen.tsx` shim for TypeScript:
|
|
82
83
|
```typescript
|
|
83
84
|
export type t<T> = { [key: string]: T };
|
|
84
85
|
```
|
|
@@ -111,7 +112,7 @@ For the generated code to compile, your project needs:
|
|
|
111
112
|
| `array` | `array<T>` |
|
|
112
113
|
| `object` | `{ field: T }` |
|
|
113
114
|
| `$ref` | type reference |
|
|
114
|
-
| `anyOf` (nullable) |
|
|
115
|
+
| `anyOf` (nullable) | `@s.nullable option<T>` |
|
|
115
116
|
| `anyOf` (union) | variant type |
|
|
116
117
|
| `oneOf` (tagged) | poly variant |
|
|
117
118
|
| `additionalProperties` | `Dict.t<T>` |
|
package/bin/osury.mjs
CHANGED
|
@@ -87,7 +87,7 @@ function generate(inputPath, outputPath) {
|
|
|
87
87
|
fs.writeFileSync(dictShimPath, Codegen.generateDictShim());
|
|
88
88
|
|
|
89
89
|
console.log(`Generated ${result._0.length} types to ${outputPath}`);
|
|
90
|
-
console.log(`Generated
|
|
90
|
+
console.log(`Generated shim: ${dictShimPath}`);
|
|
91
91
|
} else {
|
|
92
92
|
console.error("Parse errors:");
|
|
93
93
|
result._0.forEach((err) => {
|
package/package.json
CHANGED
package/src/Codegen.res.mjs
CHANGED
|
@@ -95,6 +95,7 @@ function generateType(schema) {
|
|
|
95
95
|
} else {
|
|
96
96
|
switch (schema._tag) {
|
|
97
97
|
case "Optional" :
|
|
98
|
+
case "Nullable" :
|
|
98
99
|
return `option<` + generateType(schema._0) + `>`;
|
|
99
100
|
case "Object" :
|
|
100
101
|
return generateRecord(schema._0);
|
|
@@ -116,10 +117,23 @@ function generateType(schema) {
|
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
function isOptionalType(schema) {
|
|
120
|
+
if (typeof schema !== "object") {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
switch (schema._tag) {
|
|
124
|
+
case "Optional" :
|
|
125
|
+
case "Nullable" :
|
|
126
|
+
return true;
|
|
127
|
+
default:
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function isNullableType(schema) {
|
|
119
133
|
if (typeof schema !== "object") {
|
|
120
134
|
return false;
|
|
121
135
|
} else {
|
|
122
|
-
return schema._tag === "
|
|
136
|
+
return schema._tag === "Nullable";
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
|
|
@@ -130,11 +144,10 @@ function generateRecord(fields) {
|
|
|
130
144
|
let fieldStrs = fields.map(field => {
|
|
131
145
|
let typeStr = generateType(field.type);
|
|
132
146
|
let optionalType = field.required || isOptionalType(field.type) ? typeStr : `option<` + typeStr + `>`;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
147
|
+
let nullableAttr = isNullableType(field.type) ? "@s.nullable " : "";
|
|
148
|
+
let asAttr = reservedKeywords.includes(field.name) ? `@as("` + field.name + `") ` : "";
|
|
149
|
+
let fieldName = reservedKeywords.includes(field.name) ? field.name + `_` : field.name;
|
|
150
|
+
return nullableAttr + asAttr + fieldName + `: ` + optionalType;
|
|
138
151
|
});
|
|
139
152
|
return `{\n ` + fieldStrs.join(",\n ") + `\n}`;
|
|
140
153
|
}
|
|
@@ -174,6 +187,8 @@ function getTagForType(t) {
|
|
|
174
187
|
switch (t._tag) {
|
|
175
188
|
case "Optional" :
|
|
176
189
|
return `Option` + getTagForType(t._0);
|
|
190
|
+
case "Nullable" :
|
|
191
|
+
return `Null` + getTagForType(t._0);
|
|
177
192
|
case "Object" :
|
|
178
193
|
return "Object";
|
|
179
194
|
case "Array" :
|
|
@@ -213,6 +228,7 @@ function hasUnion(_schema) {
|
|
|
213
228
|
case "PolyVariant" :
|
|
214
229
|
return schema._0.some(c => hasUnion(c.payload));
|
|
215
230
|
case "Optional" :
|
|
231
|
+
case "Nullable" :
|
|
216
232
|
case "Array" :
|
|
217
233
|
case "Dict" :
|
|
218
234
|
_schema = schema._0;
|
|
@@ -271,6 +287,7 @@ function extractUnionsFromType(_schema) {
|
|
|
271
287
|
case "Object" :
|
|
272
288
|
return schema._0.flatMap(field => extractUnionsFromType(field.type));
|
|
273
289
|
case "Optional" :
|
|
290
|
+
case "Nullable" :
|
|
274
291
|
case "Array" :
|
|
275
292
|
case "Dict" :
|
|
276
293
|
_schema = schema._0;
|
|
@@ -307,6 +324,11 @@ function replaceUnionInType(schema) {
|
|
|
307
324
|
_tag: "Optional",
|
|
308
325
|
_0: replaceUnionInType(schema._0)
|
|
309
326
|
};
|
|
327
|
+
case "Nullable" :
|
|
328
|
+
return {
|
|
329
|
+
_tag: "Nullable",
|
|
330
|
+
_0: replaceUnionInType(schema._0)
|
|
331
|
+
};
|
|
310
332
|
case "Object" :
|
|
311
333
|
let newFields = schema._0.map(field => {
|
|
312
334
|
let newType = replaceUnionInType(field.type);
|
|
@@ -377,6 +399,7 @@ function getDependencies(_schema) {
|
|
|
377
399
|
case "PolyVariant" :
|
|
378
400
|
return schema._0.flatMap(c => getDependencies(c.payload));
|
|
379
401
|
case "Optional" :
|
|
402
|
+
case "Nullable" :
|
|
380
403
|
case "Array" :
|
|
381
404
|
case "Dict" :
|
|
382
405
|
_schema = schema._0;
|
|
@@ -563,6 +586,7 @@ export {
|
|
|
563
586
|
lcFirst,
|
|
564
587
|
generateType,
|
|
565
588
|
isOptionalType,
|
|
589
|
+
isNullableType,
|
|
566
590
|
generateRecord,
|
|
567
591
|
generatePolyVariant,
|
|
568
592
|
ucFirst,
|
package/src/Schema.gen.tsx
CHANGED
package/src/Schema.res.mjs
CHANGED
|
@@ -216,7 +216,7 @@ function parseAnyOf(items) {
|
|
|
216
216
|
return {
|
|
217
217
|
TAG: "Ok",
|
|
218
218
|
_0: {
|
|
219
|
-
_tag: "
|
|
219
|
+
_tag: "Nullable",
|
|
220
220
|
_0: innerType._0
|
|
221
221
|
}
|
|
222
222
|
};
|
|
@@ -294,7 +294,7 @@ function parseAnyOf(items) {
|
|
|
294
294
|
return {
|
|
295
295
|
TAG: "Ok",
|
|
296
296
|
_0: {
|
|
297
|
-
_tag: "
|
|
297
|
+
_tag: "Nullable",
|
|
298
298
|
_0: {
|
|
299
299
|
_tag: "Union",
|
|
300
300
|
_0: types$1
|