osury 0.4.0 → 0.5.1

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
@@ -10,8 +10,8 @@ Generate ReScript types with [Sury](https://github.com/DZakh/sury) schemas from
10
10
  - Union types extracted as proper variants with `@tag("_tag")`
11
11
  - Automatic deduplication of identical union structures
12
12
  - Generates `module S = Sury` alias (required by sury-ppx)
13
- - Generates `Dict.gen.tsx` and `Null.gen.tsx` shims for TypeScript interop
14
- - Proper JSON `null` support via `Null.t<T>` (not `option` which maps to `undefined`)
13
+ - Generates `Dict.gen.tsx` shim for TypeScript interop
14
+ - Proper JSON `null` support via `@s.nullable option<T>` PPX attribute
15
15
 
16
16
  ## Installation
17
17
 
@@ -29,7 +29,7 @@ npx osury openapi.json
29
29
 
30
30
  # Generate to specific directory
31
31
  npx osury openapi.json src/API.res
32
- # Creates: src/API.res, src/Dict.gen.tsx, src/Null.gen.tsx
32
+ # Creates: src/API.res, src/Dict.gen.tsx
33
33
 
34
34
  # With explicit output flag
35
35
  npx osury generate openapi.json -o src/Schema.res
@@ -79,18 +79,11 @@ type user = {
79
79
  }
80
80
  ```
81
81
 
82
- Also generates shims for TypeScript:
83
-
84
- `Dict.gen.tsx`:
82
+ Also generates `Dict.gen.tsx` shim for TypeScript:
85
83
  ```typescript
86
84
  export type t<T> = { [key: string]: T };
87
85
  ```
88
86
 
89
- `Null.gen.tsx`:
90
- ```typescript
91
- export type t<T> = T | null;
92
- ```
93
-
94
87
  ## Generated Annotations
95
88
 
96
89
  | Annotation | Purpose |
@@ -119,7 +112,7 @@ For the generated code to compile, your project needs:
119
112
  | `array` | `array<T>` |
120
113
  | `object` | `{ field: T }` |
121
114
  | `$ref` | type reference |
122
- | `anyOf` (nullable) | `Null.t<T>` |
115
+ | `anyOf` (nullable) | `@s.nullable option<T>` |
123
116
  | `anyOf` (union) | variant type |
124
117
  | `oneOf` (tagged) | poly variant |
125
118
  | `additionalProperties` | `Dict.t<T>` |
package/bin/osury.mjs CHANGED
@@ -86,12 +86,8 @@ function generate(inputPath, outputPath) {
86
86
  const dictShimPath = path.join(outputDir || ".", "Dict.gen.tsx");
87
87
  fs.writeFileSync(dictShimPath, Codegen.generateDictShim());
88
88
 
89
- // Write Null.gen.tsx shim for @genType
90
- const nullShimPath = path.join(outputDir || ".", "Null.gen.tsx");
91
- fs.writeFileSync(nullShimPath, Codegen.generateNullShim());
92
-
93
89
  console.log(`Generated ${result._0.length} types to ${outputPath}`);
94
- console.log(`Generated shims: Dict.gen.tsx, Null.gen.tsx`);
90
+ console.log(`Generated shim: ${dictShimPath}`);
95
91
  } else {
96
92
  console.error("Parse errors:");
97
93
  result._0.forEach((err) => {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "osury",
3
3
  "type": "module",
4
4
  "description": "Generate ReScript types with Sury schemas from OpenAPI specifications",
5
- "version": "0.4.0",
5
+ "version": "0.5.1",
6
6
  "license": "MIT",
7
7
  "bin": {
8
8
  "osury": "./bin/osury.mjs"
@@ -55,6 +55,6 @@
55
55
  ],
56
56
  "repository": {
57
57
  "type": "git",
58
- "url": "https://github.com/anthropic/osury"
58
+ "url": "https://github.com/greenteamer/osury"
59
59
  }
60
60
  }
@@ -95,9 +95,8 @@ function generateType(schema) {
95
95
  } else {
96
96
  switch (schema._tag) {
97
97
  case "Optional" :
98
- return `option<` + generateType(schema._0) + `>`;
99
98
  case "Nullable" :
100
- return `Null.t<` + generateType(schema._0) + `>`;
99
+ return `option<` + generateType(schema._0) + `>`;
101
100
  case "Object" :
102
101
  return generateRecord(schema._0);
103
102
  case "Array" :
@@ -130,6 +129,14 @@ function isOptionalType(schema) {
130
129
  }
131
130
  }
132
131
 
132
+ function isNullableType(schema) {
133
+ if (typeof schema !== "object") {
134
+ return false;
135
+ } else {
136
+ return schema._tag === "Nullable";
137
+ }
138
+ }
139
+
133
140
  function generateRecord(fields) {
134
141
  if (fields.length === 0) {
135
142
  return "{}";
@@ -137,11 +144,10 @@ function generateRecord(fields) {
137
144
  let fieldStrs = fields.map(field => {
138
145
  let typeStr = generateType(field.type);
139
146
  let optionalType = field.required || isOptionalType(field.type) ? typeStr : `option<` + typeStr + `>`;
140
- if (reservedKeywords.includes(field.name)) {
141
- return `@as("` + field.name + `") ` + field.name + `_: ` + optionalType;
142
- } else {
143
- return field.name + `: ` + optionalType;
144
- }
147
+ let finalType = isNullableType(field.type) ? `@s.nullable ` + optionalType : optionalType;
148
+ let asAttr = reservedKeywords.includes(field.name) ? `@as("` + field.name + `") ` : "";
149
+ let fieldName = reservedKeywords.includes(field.name) ? field.name + `_` : field.name;
150
+ return asAttr + fieldName + `: ` + finalType;
145
151
  });
146
152
  return `{\n ` + fieldStrs.join(",\n ") + `\n}`;
147
153
  }
@@ -574,18 +580,13 @@ export type t<T> = { [key: string]: T };
574
580
  `;
575
581
  }
576
582
 
577
- function generateNullShim() {
578
- return `// Generated by osury - Null type shim for @genType
579
- export type t<T> = T | null;
580
- `;
581
- }
582
-
583
583
  export {
584
584
  reservedKeywords,
585
585
  isReservedKeyword,
586
586
  lcFirst,
587
587
  generateType,
588
588
  isOptionalType,
589
+ isNullableType,
589
590
  generateRecord,
590
591
  generatePolyVariant,
591
592
  ucFirst,
@@ -605,6 +606,5 @@ export {
605
606
  generateTypeDef,
606
607
  generateModule,
607
608
  generateDictShim,
608
- generateNullShim,
609
609
  }
610
610
  /* No side effect */