ajsc 4.0.0 → 5.0.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 +57 -9
- package/dist/TypescriptBaseConverter.d.ts +14 -1
- package/dist/TypescriptBaseConverter.js +28 -3
- package/dist/TypescriptBaseConverter.js.map +1 -1
- package/dist/TypescriptConverter.additionalProperties.test.js +110 -0
- package/dist/TypescriptConverter.additionalProperties.test.js.map +1 -0
- package/dist/TypescriptConverter.arrays.test.js +130 -0
- package/dist/TypescriptConverter.arrays.test.js.map +1 -0
- package/dist/TypescriptConverter.composites.test.d.ts +1 -0
- package/dist/TypescriptConverter.composites.test.js +13 -0
- package/dist/TypescriptConverter.composites.test.js.map +1 -0
- package/dist/TypescriptConverter.d.ts +56 -9
- package/dist/TypescriptConverter.js +105 -7
- package/dist/TypescriptConverter.js.map +1 -1
- package/dist/TypescriptConverter.objects.test.d.ts +1 -0
- package/dist/TypescriptConverter.objects.test.js +258 -0
- package/dist/TypescriptConverter.objects.test.js.map +1 -0
- package/dist/TypescriptConverter.options.test.d.ts +1 -0
- package/dist/TypescriptConverter.options.test.js +430 -0
- package/dist/TypescriptConverter.options.test.js.map +1 -0
- package/dist/TypescriptConverter.primitives.test.d.ts +1 -0
- package/dist/TypescriptConverter.primitives.test.js +26 -0
- package/dist/TypescriptConverter.primitives.test.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/dist/TypescriptConverter.test.js +0 -325
- package/dist/TypescriptConverter.test.js.map +0 -1
- package/dist/TypescriptProcedureConverter.d.ts +0 -19
- package/dist/TypescriptProcedureConverter.js +0 -54
- package/dist/TypescriptProcedureConverter.js.map +0 -1
- package/dist/TypescriptProcedureConverter.test.js +0 -997
- package/dist/TypescriptProcedureConverter.test.js.map +0 -1
- /package/dist/{TypescriptConverter.test.d.ts → TypescriptConverter.additionalProperties.test.d.ts} +0 -0
- /package/dist/{TypescriptProcedureConverter.test.d.ts → TypescriptConverter.arrays.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -102,11 +102,23 @@ console.log(converter.irNode);
|
|
|
102
102
|
The package includes a TypeScript language plugin that converts the IRNode into TypeScript type definitions.
|
|
103
103
|
|
|
104
104
|
- Constructor:
|
|
105
|
-
`new TypescriptConverter(schema: object, options?:
|
|
105
|
+
`new TypescriptConverter(schema: object, options?: TypescriptConverterOpts)`
|
|
106
106
|
- Properties:
|
|
107
107
|
- code: A string containing the generated TypeScript code.
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
#### Options
|
|
110
|
+
|
|
111
|
+
| Option | Type | Default | Description |
|
|
112
|
+
|--------|------|---------|-------------|
|
|
113
|
+
| `inlineTypes` | `boolean` | `false` | If true, object types are inlined instead of extracted as named type aliases. |
|
|
114
|
+
| `depluralize` | `boolean` | `true` | Singularize array item type names. Handles irregular plurals (e.g. `entries` → `Entry`, `people` → `Person`). |
|
|
115
|
+
| `arrayItemNaming` | `string \| false` | `false` | Controls the postfix for array item type names. `false` = no postfix, `string` = custom postfix (e.g. `"Item"` → `ContactItem`). |
|
|
116
|
+
| `enumStyle` | `"union" \| "enum"` | `"union"` | `"union"` emits `"a" \| "b"`, `"enum"` emits `export enum`. Only applies when `inlineTypes` is false and all values are strings. |
|
|
117
|
+
| `uncountableWords` | `string[]` | `undefined` | Additional words that should not be singularized (built-in: `"data"`, `"metadata"`). |
|
|
118
|
+
|
|
119
|
+
#### Usage Examples
|
|
120
|
+
|
|
121
|
+
Default behavior — array item types are automatically singularized:
|
|
110
122
|
|
|
111
123
|
```javascript
|
|
112
124
|
import { TypescriptConverter } from "ajsc";
|
|
@@ -137,14 +149,50 @@ const schema = {
|
|
|
137
149
|
required: ["name", "age"],
|
|
138
150
|
};
|
|
139
151
|
|
|
152
|
+
const tsConverter = new TypescriptConverter(schema);
|
|
153
|
+
console.log(tsConverter.code);
|
|
154
|
+
|
|
155
|
+
// Output:
|
|
156
|
+
// export type Contact = { email: string; };
|
|
157
|
+
// export type Profile = { email: string; };
|
|
158
|
+
//
|
|
159
|
+
// export type Root = { name: string; age: number; contacts?: Array<Contact>; profile?: Profile; };
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Inline types (no extracted type aliases):
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
140
165
|
const tsConverter = new TypescriptConverter(schema, { inlineTypes: true });
|
|
141
166
|
console.log(tsConverter.code);
|
|
142
167
|
|
|
143
|
-
//
|
|
144
|
-
// {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
// Output:
|
|
169
|
+
// { name: string; age: number; contacts?: Array<{ email: string; }>; profile?: { email: string; }; }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Enum style:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
const enumSchema = {
|
|
176
|
+
type: "object",
|
|
177
|
+
properties: {
|
|
178
|
+
status: { type: "string", enum: ["active", "inactive", "pending"] },
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const tsConverter = new TypescriptConverter(enumSchema, { enumStyle: "enum" });
|
|
183
|
+
console.log(tsConverter.code);
|
|
184
|
+
|
|
185
|
+
// Output:
|
|
186
|
+
// export enum Status { Active = "active", Inactive = "inactive", Pending = "pending" }
|
|
187
|
+
//
|
|
188
|
+
// export type Root = { status?: Status; };
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Custom uncountable words:
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const tsConverter = new TypescriptConverter(schema, {
|
|
195
|
+
uncountableWords: ["criteria", "alumni"],
|
|
196
|
+
});
|
|
197
|
+
// "criteria" array items will produce type "Criteria", not "Criterium"
|
|
150
198
|
```
|
|
@@ -10,12 +10,24 @@ export type RefTypes = [
|
|
|
10
10
|
export interface RefTypeNamingConfig {
|
|
11
11
|
/** Base postfixes to try for name collision resolution */
|
|
12
12
|
postfixes: string[];
|
|
13
|
-
/** If true,
|
|
13
|
+
/** If true, singularize array item path segments (e.g. "entries" → "entry", "people" → "person") */
|
|
14
14
|
depluralize?: boolean;
|
|
15
15
|
/** If true, handle "*" path endings with AnyKey/AnyProperty postfixes */
|
|
16
16
|
handleAnySymbol?: boolean;
|
|
17
17
|
/** If true, strip leading "*" from proposed names */
|
|
18
18
|
stripLeadingAnySymbol?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Controls the postfix added to array item type names.
|
|
21
|
+
* - `false` (default) → no postfix, uses property name directly
|
|
22
|
+
* - `string` → custom postfix (e.g. "Item" → ContactsItem, "Element" → ContactsElement)
|
|
23
|
+
*/
|
|
24
|
+
arrayItemNaming?: string | false;
|
|
25
|
+
/**
|
|
26
|
+
* Additional words that should not be singularized when `depluralize` is true.
|
|
27
|
+
* Built-in uncountables: "data", "metadata".
|
|
28
|
+
* @example ["criteria", "alumni", "corpus"]
|
|
29
|
+
*/
|
|
30
|
+
uncountableWords?: string[];
|
|
19
31
|
}
|
|
20
32
|
export type GenerateTypeUtils = {
|
|
21
33
|
getReferencedType(ir: IRNode): string | undefined;
|
|
@@ -41,6 +53,7 @@ export declare abstract class TypescriptBaseConverter {
|
|
|
41
53
|
*/
|
|
42
54
|
protected generateObjectType(ir: IRNode, utils: GenerateTypeUtils): string;
|
|
43
55
|
protected isValidIdentifier(name: string): boolean;
|
|
56
|
+
private singularize;
|
|
44
57
|
protected makeTypeReferenceName(signatureOccurrences: SignatureOccurrenceValue["occurrences"]): string;
|
|
45
58
|
protected getUniqueRefTypeName(signature: string, nodePath: string): RefTypeName;
|
|
46
59
|
protected getReferencedType(ir: IRNode): string | undefined;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import pluralize from "pluralize";
|
|
1
2
|
import { PathUtils } from "./utils/path-utils.js";
|
|
2
3
|
import { toPascalCase } from "./utils/to-pascal-case.js";
|
|
4
|
+
/** Default words that should not be singularized (common programming/API terms). */
|
|
5
|
+
const DEFAULT_UNCOUNTABLE_WORDS = ["data", "metadata"];
|
|
3
6
|
export class TypescriptBaseConverter {
|
|
4
7
|
constructor() {
|
|
5
8
|
this.refTypes = [];
|
|
@@ -14,7 +17,8 @@ export class TypescriptBaseConverter {
|
|
|
14
17
|
],
|
|
15
18
|
handleAnySymbol: true,
|
|
16
19
|
stripLeadingAnySymbol: true,
|
|
17
|
-
depluralize:
|
|
20
|
+
depluralize: true,
|
|
21
|
+
arrayItemNaming: false,
|
|
18
22
|
};
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
@@ -152,6 +156,13 @@ export class TypescriptBaseConverter {
|
|
|
152
156
|
isValidIdentifier(name) {
|
|
153
157
|
return /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
|
|
154
158
|
}
|
|
159
|
+
singularize(word, extraUncountable) {
|
|
160
|
+
const uncountable = [...DEFAULT_UNCOUNTABLE_WORDS, ...(extraUncountable ?? [])];
|
|
161
|
+
if (uncountable.some((u) => word.toLowerCase().endsWith(u.toLowerCase()))) {
|
|
162
|
+
return word;
|
|
163
|
+
}
|
|
164
|
+
return pluralize.singular(word);
|
|
165
|
+
}
|
|
155
166
|
makeTypeReferenceName(signatureOccurrences) {
|
|
156
167
|
const paths = PathUtils.parsePaths(signatureOccurrences.map((occurrence) => occurrence.nodePath));
|
|
157
168
|
const common = PathUtils.commonSequence(paths);
|
|
@@ -165,9 +176,14 @@ export class TypescriptBaseConverter {
|
|
|
165
176
|
const isAnySymbol = lastPathItem === "*";
|
|
166
177
|
const postFixes = [...config.postfixes];
|
|
167
178
|
if (isArrayItem) {
|
|
168
|
-
|
|
179
|
+
if (config.arrayItemNaming !== false) {
|
|
180
|
+
postFixes.unshift(config.arrayItemNaming ?? "Item");
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
postFixes.unshift("");
|
|
184
|
+
}
|
|
169
185
|
if (config.depluralize && path.length > 0 && path[path.length - 1]) {
|
|
170
|
-
path[path.length - 1] = path[path.length - 1].
|
|
186
|
+
path[path.length - 1] = this.singularize(path[path.length - 1], config.uncountableWords);
|
|
171
187
|
}
|
|
172
188
|
}
|
|
173
189
|
else if (config.handleAnySymbol && isAnySymbol) {
|
|
@@ -189,6 +205,15 @@ export class TypescriptBaseConverter {
|
|
|
189
205
|
if (foundSignatureMatch) {
|
|
190
206
|
return foundSignatureMatch[1];
|
|
191
207
|
}
|
|
208
|
+
// Skip empty proposed names (e.g. empty path with no postfix)
|
|
209
|
+
if (!proposedName) {
|
|
210
|
+
postFixIndexToTry++;
|
|
211
|
+
if (postFixIndexToTry >= postFixes.length) {
|
|
212
|
+
this.fallbackCounter++;
|
|
213
|
+
name = "Type" + this.fallbackCounter;
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
192
217
|
const nameAlreadyUsed = this.refTypes.find(([_sig, n]) => n === proposedName);
|
|
193
218
|
if (nameAlreadyUsed) {
|
|
194
219
|
pathsSegmentsToInclude++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypescriptBaseConverter.js","sourceRoot":"","sources":["../src/TypescriptBaseConverter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TypescriptBaseConverter.js","sourceRoot":"","sources":["../src/TypescriptBaseConverter.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,oFAAoF;AACpF,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAqCvD,MAAM,OAAgB,uBAAuB;IAA7C;QAGY,aAAQ,GAAa,EAAE,CAAC;QAC1B,oBAAe,GAAG,CAAC,CAAC;IAqS9B,CAAC;IAnSW,sBAAsB;QAC9B,OAAO;YACL,SAAS,EAAE;gBACT,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY;gBAC5D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;gBACtD,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK;aACvC;YACD,eAAe,EAAE,IAAI;YACrB,qBAAqB,EAAE,IAAI;YAC3B,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,EAAU,EAAE,KAAwB;QACzD,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBACnD,IAAI,cAAc;oBAAE,OAAO,cAAc,CAAC;gBAC1C,OAAO,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC3C,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC3C,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC3C,KAAK,cAAc;gBACjB,OAAO,IAAI,CAAC,wBAAwB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAClD,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACnC,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;YACtC,KAAK,KAAK;gBACR,OAAO,KAAK,CAAC;YACf,KAAK,SAAS;gBACZ,OAAO,SAAS,CAAC;YACnB,KAAK,OAAO;gBACV,OAAO,OAAO,CAAC;YACjB,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAChD,IAAI,EAAE,CAAC,IAAI,IAAI,YAAY,EAAE,CAAC;oBAC5B,OAAO,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAES,iBAAiB,CAAC,EAAU,EAAE,KAAwB;QAC9D,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,OAAO,SAAS,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;QACxD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,iBAAiB,CAAC,EAAU,EAAE,KAAwB;QAC9D,IAAI,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7E,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAES,iBAAiB,CAAC,EAAU,EAAE,KAAwB;QAC9D,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,EAAE,CAAC,OAAO;iBACd,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;iBAC3C,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,wBAAwB,CAAC,EAAU,EAAE,KAAwB;QACrE,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,EAAE,CAAC,OAAO;iBACd,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;iBAC3C,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,gBAAgB,CAAC,EAAU;QACnC,IAAI,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,mBAAmB,CAAC,EAAU;QACtC,OAAO,OAAO,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,QAAQ;YAC9C,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC;YACtC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAES,mBAAmB;QAC3B,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAED;;OAEG;IACO,kBAAkB,CAAC,EAAU,EAAE,KAAwB;QAC/D,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,MAAM,yBAAyB,GAAG,IAAI,GAAG,EAAU,CAAC;QAEpD,IAAI,EAAE,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;YACrC,yBAAyB,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACvD,CAAC;aAAM,IAAI,EAAE,CAAC,oBAAoB,EAAE,CAAC;YACnC,yBAAyB,CAAC,GAAG,CAC3B,kBAAkB,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,oBAAoB,EAAE;gBAC3D,4DAA4D;gBAC5D,iBAAiB;oBACf,OAAO,SAAS,CAAC;gBACnB,CAAC;aACF,CAAC,GAAG,CACN,CAAC;QACJ,CAAC;QAED,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBACnD,MAAM,IAAI,GAAG,EAAE,CAAC,UAAW,CAAC,GAAG,CAAC,CAAC;gBACjC,8CAA8C;gBAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC1C,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;YAC5G,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,yBAAyB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC1D,yBAAyB,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YAC7D,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACxB,SAAS,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACvC,CAAC;QACH,CAAC;QAED,IAAI,WAAW,GAAG,EAAE,CAAC;QAErB,IAAI,yBAAyB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,SAAS,EAAE,CAAC;gBACd,WAAW,GAAG,IAAI,SAAS,OAAO,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAC1F,CAAC;iBAAM,CAAC;gBACN,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,SAAS,IAAI,2BAA2B,CAAC;QACzD,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAES,iBAAiB,CAAC,IAAY;QACtC,OAAO,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAEO,WAAW,CAAC,IAAY,EAAE,gBAA2B;QAC3D,MAAM,WAAW,GAAG,CAAC,GAAG,yBAAyB,EAAE,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC;QAChF,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAES,qBAAqB,CAC7B,oBAA6D;QAE7D,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAChC,oBAAoB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAC9D,CAAC;QACF,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAES,oBAAoB,CAC5B,SAAiB,EACjB,QAAgB;QAEhB,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,YAAY,KAAK,GAAG,CAAC;QACzC,MAAM,WAAW,GAAG,YAAY,KAAK,GAAG,CAAC;QAEzC,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAExC,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,MAAM,CAAC,eAAe,KAAK,KAAK,EAAE,CAAC;gBACrC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gBACnE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,eAAe,IAAI,WAAW,EAAE,CAAC;YACjD,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;QAED,IAAI,sBAAsB,GAAG,CAAC,CAAC;QAC/B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAE1B,OAAO,CAAC,IAAI,EAAE,CAAC;YACb,IAAI,YAAY,GACd,IAAI,CAAC,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9D,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAE/B,IAAI,MAAM,CAAC,qBAAqB,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC5D,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAC5C,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,KAAK,YAAY,CACtD,CAAC;YACF,IAAI,mBAAmB,EAAE,CAAC;gBACxB,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC;YAChC,CAAC;YAED,8DAA8D;YAC9D,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,iBAAiB,EAAE,CAAC;gBACpB,IAAI,iBAAiB,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;oBAC1C,IAAI,CAAC,eAAe,EAAE,CAAC;oBACvB,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC;gBACvC,CAAC;gBACD,SAAS;YACX,CAAC;YAED,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CACxC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,CAClC,CAAC;YAEF,IAAI,eAAe,EAAE,CAAC;gBACpB,sBAAsB,EAAE,CAAC;gBACzB,IAAI,sBAAsB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC1C,iBAAiB,EAAE,CAAC;oBACpB,sBAAsB,GAAG,CAAC,CAAC;oBAE3B,IAAI,iBAAiB,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;wBAC3C,yCAAyC;wBACzC,IAAI,CAAC,eAAe,EAAE,CAAC;wBACvB,IAAI,GAAG,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC;oBAC7C,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,YAAY,CAAC;YACtB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAES,iBAAiB,CAAC,EAAU;QACpC,MAAM,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC;QAE/B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAE3D,sEAAsE;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CACjC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CACtD,CAAC;QACF,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8EAA8E;QAC9E,MAAM,KAAK,GAAqB,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE1B,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE;YACvC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;SACrD,CAAC,CAAC;QAEH,uCAAuC;QACvC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;QAErB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { TypescriptConverter } from "./TypescriptConverter.js";
|
|
3
|
+
describe("TypescriptConverter - additionalProperties and patternProperties", () => {
|
|
4
|
+
it("should convert objects with only additionalProperties", async () => {
|
|
5
|
+
expect(new TypescriptConverter({
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
metadata: {
|
|
9
|
+
type: "object",
|
|
10
|
+
additionalProperties: { type: "string" },
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ["metadata"],
|
|
14
|
+
}, {
|
|
15
|
+
inlineTypes: true,
|
|
16
|
+
}).code.replace(/\s/g, "")).toEqual(`{metadata: Record<string, string>; }`.replace(/\s/g, ""));
|
|
17
|
+
});
|
|
18
|
+
it("should convert objects with mixed properties & additionalProperties", async () => {
|
|
19
|
+
expect(new TypescriptConverter({
|
|
20
|
+
type: "object",
|
|
21
|
+
properties: {
|
|
22
|
+
metadata: {
|
|
23
|
+
type: "object",
|
|
24
|
+
additionalProperties: { type: "string" },
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
additionalProperties: { type: "string" },
|
|
28
|
+
required: ["metadata"],
|
|
29
|
+
}, {
|
|
30
|
+
inlineTypes: true,
|
|
31
|
+
}).code.replace(/\s/g, "")).toEqual(`({metadata:Record<string,string>;}&(Record<string,string>))`.replace(/\s/g, ""));
|
|
32
|
+
});
|
|
33
|
+
it("should convert objects with complex additionalProperties", async () => {
|
|
34
|
+
expect(new TypescriptConverter({
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
specificProp: {
|
|
38
|
+
type: "string",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: {
|
|
42
|
+
type: "object",
|
|
43
|
+
properties: {
|
|
44
|
+
subAdditionalProp: { type: "string" },
|
|
45
|
+
},
|
|
46
|
+
additionalProperties: { type: "string" },
|
|
47
|
+
},
|
|
48
|
+
required: ["metadata"],
|
|
49
|
+
}, {
|
|
50
|
+
inlineTypes: true,
|
|
51
|
+
}).code.replace(/\s/g, "")).toEqual(`({specificProp?:string;}&(Record<string,({subAdditionalProp?:string;}&(Record<string,string>))>))`.replace(/\s/g, ""));
|
|
52
|
+
});
|
|
53
|
+
it("should convert { type: 'object', additionalProperties: true } to Record<string, any>", () => {
|
|
54
|
+
expect(new TypescriptConverter({
|
|
55
|
+
type: "object",
|
|
56
|
+
additionalProperties: true,
|
|
57
|
+
}, { inlineTypes: true }).code.replace(/\s/g, "")).toEqual("Record<string,any>".replace(/\s/g, ""));
|
|
58
|
+
});
|
|
59
|
+
it("should render additionalProperties: false without extra Record types", () => {
|
|
60
|
+
expect(new TypescriptConverter({
|
|
61
|
+
type: "object",
|
|
62
|
+
properties: {
|
|
63
|
+
name: { type: "string" },
|
|
64
|
+
},
|
|
65
|
+
additionalProperties: false,
|
|
66
|
+
required: ["name"],
|
|
67
|
+
}, { inlineTypes: true }).code.replace(/\s/g, "")).toEqual("{ name: string; }".replace(/\s/g, ""));
|
|
68
|
+
});
|
|
69
|
+
it("should convert a JSON schema with pattern properties", () => {
|
|
70
|
+
expect(new TypescriptConverter({
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
totalTodo: {
|
|
74
|
+
type: "number",
|
|
75
|
+
},
|
|
76
|
+
totalPastDue: {
|
|
77
|
+
type: "number",
|
|
78
|
+
},
|
|
79
|
+
unassignedTodo: {
|
|
80
|
+
type: "number",
|
|
81
|
+
},
|
|
82
|
+
todoByAssignee: {
|
|
83
|
+
type: "object",
|
|
84
|
+
patternProperties: {
|
|
85
|
+
"^(.*)$": {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
todo: {
|
|
89
|
+
type: "number",
|
|
90
|
+
},
|
|
91
|
+
pastDue: {
|
|
92
|
+
type: "number",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
required: ["todo", "pastDue"],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
required: [
|
|
101
|
+
"totalTodo",
|
|
102
|
+
"totalPastDue",
|
|
103
|
+
"unassignedTodo",
|
|
104
|
+
"todoByAssignee",
|
|
105
|
+
],
|
|
106
|
+
title: "Root",
|
|
107
|
+
}).code.replace(/\s/g, "")).toEqual("export type TodoByAssignee = Record<string, { todo: number; pastDue: number; }>;export type Root = { totalTodo: number; totalPastDue: number; unassignedTodo: number; todoByAssignee: TodoByAssignee; };".replace(/\s/g, ""));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=TypescriptConverter.additionalProperties.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypescriptConverter.additionalProperties.test.js","sourceRoot":"","sources":["../src/TypescriptConverter.additionalProperties.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { TypescriptConverter } from "./TypescriptConverter.js";
|
|
3
|
+
describe("TypescriptConverter - arrays (inlineTypes)", () => {
|
|
4
|
+
it("should convert arrays", () => {
|
|
5
|
+
expect(new TypescriptConverter({
|
|
6
|
+
title: "MyArray",
|
|
7
|
+
type: "array",
|
|
8
|
+
items: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: { name: { type: "string" } },
|
|
11
|
+
required: ["name"],
|
|
12
|
+
},
|
|
13
|
+
}, {
|
|
14
|
+
inlineTypes: true,
|
|
15
|
+
}).code.replace(/\s/g, "")).toEqual("Array<{name:string;}>".replace(/\s/g, ""));
|
|
16
|
+
});
|
|
17
|
+
it("should convert an array of objects", () => {
|
|
18
|
+
expect(new TypescriptConverter({
|
|
19
|
+
type: "array",
|
|
20
|
+
items: {
|
|
21
|
+
anyOf: [
|
|
22
|
+
{
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
year: { type: "number" },
|
|
26
|
+
},
|
|
27
|
+
required: ["year"],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
title: { type: "string" },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
}, {
|
|
38
|
+
inlineTypes: true,
|
|
39
|
+
}).code).toMatch(`Array<{ year: number; } | { title?: string; }>`);
|
|
40
|
+
});
|
|
41
|
+
it("should convert a named JSON schema top-level array to Typescript", () => {
|
|
42
|
+
expect(new TypescriptConverter({
|
|
43
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
44
|
+
title: "People",
|
|
45
|
+
type: "array",
|
|
46
|
+
items: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
name: { type: "string" },
|
|
50
|
+
age: { type: "number" },
|
|
51
|
+
},
|
|
52
|
+
required: ["name", "age"],
|
|
53
|
+
},
|
|
54
|
+
}, {
|
|
55
|
+
inlineTypes: true,
|
|
56
|
+
}).code.replace(/\s/g, "")).toEqual(`Array<{ name: string; age: number; }>`.replace(/\s/g, ""));
|
|
57
|
+
});
|
|
58
|
+
it("should render tuple types as [T1, T2, ...]", () => {
|
|
59
|
+
expect(new TypescriptConverter({
|
|
60
|
+
type: "array",
|
|
61
|
+
items: [{ type: "string" }, { type: "number" }],
|
|
62
|
+
}, { inlineTypes: true }).code).toBe("[string, number]");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe("TypescriptConverter - arrays (full type defs)", () => {
|
|
66
|
+
it("should convert arrays", () => {
|
|
67
|
+
expect(new TypescriptConverter({
|
|
68
|
+
title: "MyArray",
|
|
69
|
+
type: "array",
|
|
70
|
+
items: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: { name: { type: "string" } },
|
|
73
|
+
required: ["name"],
|
|
74
|
+
},
|
|
75
|
+
}, {}).code.replace(/\s/g, "")).toEqual("export type Type={name:string;}; export type MyArray=Array<Type>;".replace(/\s/g, ""));
|
|
76
|
+
});
|
|
77
|
+
it("should convert an array of objects", () => {
|
|
78
|
+
expect(new TypescriptConverter({
|
|
79
|
+
type: "array",
|
|
80
|
+
items: {
|
|
81
|
+
anyOf: [
|
|
82
|
+
{
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: {
|
|
85
|
+
year: { type: "number" },
|
|
86
|
+
},
|
|
87
|
+
required: ["year"],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
title: { type: "string" },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
}, {}).code.replace(/\s/g, "")).toMatch(`
|
|
98
|
+
export type Type = { year: number; };
|
|
99
|
+
|
|
100
|
+
export type Element = { title?: string; };
|
|
101
|
+
|
|
102
|
+
export type Root = Array<Type | Element>;
|
|
103
|
+
`.replace(/\s/g, ""));
|
|
104
|
+
});
|
|
105
|
+
it("should convert a named JSON schema top-level array to Typescript", () => {
|
|
106
|
+
expect(new TypescriptConverter({
|
|
107
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
108
|
+
title: "People",
|
|
109
|
+
type: "array",
|
|
110
|
+
items: {
|
|
111
|
+
type: "object",
|
|
112
|
+
properties: {
|
|
113
|
+
name: { type: "string" },
|
|
114
|
+
age: { type: "number" },
|
|
115
|
+
},
|
|
116
|
+
required: ["name", "age"],
|
|
117
|
+
},
|
|
118
|
+
}, {}).code.replace(/\s/g, "")).toEqual(`
|
|
119
|
+
export type Type = {name:string;age:number;};
|
|
120
|
+
|
|
121
|
+
export type People = Array<Type>;`.replace(/\s/g, ""));
|
|
122
|
+
});
|
|
123
|
+
it("should render tuple types as [T1, T2, ...]", () => {
|
|
124
|
+
expect(new TypescriptConverter({
|
|
125
|
+
type: "array",
|
|
126
|
+
items: [{ type: "string" }, { type: "number" }],
|
|
127
|
+
}, {}).code.replace(/\s/g, "")).toBe(`export type Root = [string, number];`.replace(/\s/g, ""));
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=TypescriptConverter.arrays.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypescriptConverter.arrays.test.js","sourceRoot":"","sources":["../src/TypescriptConverter.arrays.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { TypescriptConverter } from "./TypescriptConverter.js";
|
|
3
|
+
describe("TypescriptConverter - unions and intersections", () => {
|
|
4
|
+
it("should convert unions", () => {
|
|
5
|
+
expect(new TypescriptConverter({ type: ["string", "number"] }).code).toMatch(`string | number`);
|
|
6
|
+
});
|
|
7
|
+
it("should convert intersections", () => {
|
|
8
|
+
expect(new TypescriptConverter({
|
|
9
|
+
allOf: [{ type: "string" }, { type: "number" }],
|
|
10
|
+
}).code).toMatch(`string & number`);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=TypescriptConverter.composites.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypescriptConverter.composites.test.js","sourceRoot":"","sources":["../src/TypescriptConverter.composites.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CACJ,IAAI,mBAAmB,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAC7D,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CACJ,IAAI,mBAAmB,CAAC;YACtB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;SAChD,CAAC,CAAC,IAAI,CACR,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,18 +1,65 @@
|
|
|
1
|
-
import { ILanguageConverter } from "./types.js";
|
|
2
|
-
import { TypescriptBaseConverter } from "./TypescriptBaseConverter.js";
|
|
1
|
+
import { ILanguageConverter, IRNode } from "./types.js";
|
|
2
|
+
import { RefTypeNamingConfig, TypescriptBaseConverter } from "./TypescriptBaseConverter.js";
|
|
3
3
|
import { JSONSchema7Definition } from "json-schema";
|
|
4
|
+
export interface TypescriptConverterOpts {
|
|
5
|
+
/**
|
|
6
|
+
* If true, referenced types will not be created for objects and instead
|
|
7
|
+
* the object type will be inlined.
|
|
8
|
+
*/
|
|
9
|
+
inlineTypes?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Controls the postfix added to array item type names.
|
|
12
|
+
* - `false` (default) → no postfix, uses property name directly
|
|
13
|
+
* - `string` → custom postfix (e.g. "Item" → ContactsItem, "Element" → ContactsElement)
|
|
14
|
+
*/
|
|
15
|
+
arrayItemNaming?: string | false;
|
|
16
|
+
/**
|
|
17
|
+
* If true (default), singularize array item path segments when generating type names.
|
|
18
|
+
* Handles irregular plurals (e.g. "entries" → "Entry", "people" → "Person").
|
|
19
|
+
*/
|
|
20
|
+
depluralize?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Controls how enum values are emitted.
|
|
23
|
+
* - `"union"` (default) → `"a" | "b" | "c"`
|
|
24
|
+
* - `"enum"` → `export enum Status { A = "a", B = "b", C = "c" }`
|
|
25
|
+
* Only applies when `inlineTypes` is false and all values are strings.
|
|
26
|
+
*/
|
|
27
|
+
enumStyle?: "union" | "enum";
|
|
28
|
+
/**
|
|
29
|
+
* Additional words that should not be singularized when `depluralize` is true.
|
|
30
|
+
* Built-in uncountables: "data", "metadata".
|
|
31
|
+
* @example ["criteria", "alumni", "corpus"]
|
|
32
|
+
*/
|
|
33
|
+
uncountableWords?: string[];
|
|
34
|
+
}
|
|
4
35
|
/**
|
|
5
36
|
* A TypeScript language converter plugin.
|
|
6
37
|
*/
|
|
7
38
|
export declare class TypescriptConverter extends TypescriptBaseConverter implements ILanguageConverter {
|
|
8
39
|
readonly language = "typescript";
|
|
9
40
|
private schemaConverter;
|
|
41
|
+
private opts;
|
|
42
|
+
private inlineTypes;
|
|
43
|
+
private enumStyle;
|
|
44
|
+
/**
|
|
45
|
+
* Stores enum declarations keyed by canonical signature (sorted JSON values)
|
|
46
|
+
* for deduplication across the schema.
|
|
47
|
+
*/
|
|
48
|
+
private enumDeclarations;
|
|
49
|
+
/** Tracks all enum declaration names for collision resolution */
|
|
50
|
+
private usedEnumNames;
|
|
10
51
|
readonly code: string;
|
|
11
|
-
constructor(schema: JSONSchema7Definition, opts?:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
52
|
+
constructor(schema: JSONSchema7Definition, opts?: TypescriptConverterOpts);
|
|
53
|
+
protected getRefTypeNamingConfig(): RefTypeNamingConfig;
|
|
54
|
+
protected generateEnumType(ir: IRNode): string;
|
|
55
|
+
protected generateLiteralType(ir: IRNode): string;
|
|
56
|
+
/**
|
|
57
|
+
* Returns (or creates) a deduplicated enum declaration for the given string values.
|
|
58
|
+
* Same set of values at different paths reuses the same enum.
|
|
59
|
+
*/
|
|
60
|
+
private getOrCreateEnumDeclaration;
|
|
61
|
+
/**
|
|
62
|
+
* Converts a string value to a valid PascalCase enum member name.
|
|
63
|
+
*/
|
|
64
|
+
private toEnumMemberName;
|
|
18
65
|
}
|