@kemdict/json-to-ts 0.1.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/LICENSE +6 -0
- package/README.md +96 -0
- package/dist/get-interfaces.d.ts +6 -0
- package/dist/get-interfaces.d.ts.map +1 -0
- package/dist/get-interfaces.js +99 -0
- package/dist/get-interfaces.js.map +1 -0
- package/dist/get-names.d.ts +3 -0
- package/dist/get-names.d.ts.map +1 -0
- package/dist/get-names.js +147 -0
- package/dist/get-names.js.map +1 -0
- package/dist/get-type-structure.d.ts +5 -0
- package/dist/get-type-structure.d.ts.map +1 -0
- package/dist/get-type-structure.js +258 -0
- package/dist/get-type-structure.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/model.d.ts +62 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +2 -0
- package/dist/model.js.map +1 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +49 -0
- package/dist/util.js.map +1 -0
- package/package.json +40 -0
- package/src/get-interfaces.ts +121 -0
- package/src/get-names.ts +218 -0
- package/src/get-type-structure.ts +308 -0
- package/src/index.ts +39 -0
- package/src/model.ts +65 -0
- package/src/util.ts +63 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { hash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import type { TypeGroup, TypeDescription, TypeStructure } from "./model.ts";
|
|
4
|
+
import { isHash, getTypeDescriptionGroup, findTypeById, isArray, isObject, onlyUnique, isDate } from "./util.ts";
|
|
5
|
+
|
|
6
|
+
function createTypeDescription(typeObj: any | string[], isUnion: boolean): TypeDescription {
|
|
7
|
+
if (isArray(typeObj)) {
|
|
8
|
+
return {
|
|
9
|
+
id: Hash(JSON.stringify([...typeObj, isUnion])),
|
|
10
|
+
arrayOfTypes: typeObj,
|
|
11
|
+
isUnion,
|
|
12
|
+
};
|
|
13
|
+
} else {
|
|
14
|
+
return {
|
|
15
|
+
id: Hash(JSON.stringify(typeObj)),
|
|
16
|
+
typeObj,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getIdByType(typeObj: any | string[], types: TypeDescription[], isUnion: boolean = false): string {
|
|
22
|
+
let typeDesc = types.find((el) => {
|
|
23
|
+
return typeObjectMatchesTypeDesc(typeObj, el, isUnion);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!typeDesc) {
|
|
27
|
+
typeDesc = createTypeDescription(typeObj, isUnion);
|
|
28
|
+
types.push(typeDesc);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return typeDesc.id;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function Hash(content: string): string {
|
|
35
|
+
return hash("sha1", content);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function typeObjectMatchesTypeDesc(typeObj: any | string[], typeDesc: TypeDescription, isUnion: boolean): boolean {
|
|
39
|
+
if (isArray(typeObj)) {
|
|
40
|
+
return arraysContainSameElements(typeObj, typeDesc.arrayOfTypes!) && typeDesc.isUnion === isUnion;
|
|
41
|
+
} else {
|
|
42
|
+
return objectsHaveSameEntries(typeObj, typeDesc.typeObj);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function arraysContainSameElements(arr1: any[], arr2: any[]): boolean {
|
|
47
|
+
if (arr1 === undefined || arr2 === undefined) return false;
|
|
48
|
+
|
|
49
|
+
return arr1.sort().join("") === arr2.sort().join("");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function objectsHaveSameEntries(obj1: any, obj2: any): boolean {
|
|
53
|
+
if (obj1 === undefined || obj2 === undefined) return false;
|
|
54
|
+
|
|
55
|
+
const entries1 = Object.entries(obj1);
|
|
56
|
+
const entries2 = Object.entries(obj2);
|
|
57
|
+
|
|
58
|
+
const sameLength = entries1.length === entries2.length;
|
|
59
|
+
|
|
60
|
+
const sameTypes = entries1.every(([key, value]) => {
|
|
61
|
+
return obj2[key] === value;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return sameLength && sameTypes;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getSimpleTypeName(value: any): string {
|
|
68
|
+
if (value === null) {
|
|
69
|
+
return "null";
|
|
70
|
+
} else if (value instanceof Date) {
|
|
71
|
+
return "Date";
|
|
72
|
+
} else {
|
|
73
|
+
return typeof value;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getTypeGroup(value: any): TypeGroup {
|
|
78
|
+
if (isDate(value)) {
|
|
79
|
+
return "date";
|
|
80
|
+
} else if (isArray(value)) {
|
|
81
|
+
return "array";
|
|
82
|
+
} else if (isObject(value)) {
|
|
83
|
+
return "object";
|
|
84
|
+
} else {
|
|
85
|
+
return "primitive";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function createTypeObject(obj: any, types: TypeDescription[]): any {
|
|
90
|
+
return Object.entries(obj).reduce((typeObj, [key, value]) => {
|
|
91
|
+
const { rootTypeId } = getTypeStructure(value, types);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
...typeObj,
|
|
95
|
+
[key]: rootTypeId,
|
|
96
|
+
};
|
|
97
|
+
}, {});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getMergedObjects(typesOfArray: TypeDescription[], types: TypeDescription[]): string {
|
|
101
|
+
const typeObjects = typesOfArray.map((typeDesc) => typeDesc.typeObj);
|
|
102
|
+
|
|
103
|
+
const allKeys = typeObjects
|
|
104
|
+
.map((typeObj) => Object.keys(typeObj!))
|
|
105
|
+
.reduce((a, b) => [...a, ...b], [])
|
|
106
|
+
.filter(onlyUnique);
|
|
107
|
+
|
|
108
|
+
const commonKeys = typeObjects.reduce((commonKeys: string[], typeObj) => {
|
|
109
|
+
const keys = Object.keys(typeObj!);
|
|
110
|
+
return commonKeys.filter((key) => keys.includes(key));
|
|
111
|
+
}, allKeys) as string[];
|
|
112
|
+
|
|
113
|
+
const getKeyType = (key: string) => {
|
|
114
|
+
const typesOfKey = typeObjects
|
|
115
|
+
.filter((typeObj) => {
|
|
116
|
+
return Object.keys(typeObj!).includes(key);
|
|
117
|
+
})
|
|
118
|
+
.map((typeObj) => typeObj![key])
|
|
119
|
+
.filter(onlyUnique);
|
|
120
|
+
|
|
121
|
+
if (typesOfKey.length === 1) {
|
|
122
|
+
return typesOfKey.pop();
|
|
123
|
+
} else {
|
|
124
|
+
return getInnerArrayType(typesOfKey, types);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const typeObj = allKeys.reduce((obj: object, key: string) => {
|
|
129
|
+
const isMandatory = commonKeys.includes(key);
|
|
130
|
+
const type = getKeyType(key);
|
|
131
|
+
|
|
132
|
+
const keyValue = isMandatory ? key : toOptionalKey(key);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
...obj,
|
|
136
|
+
[keyValue]: type,
|
|
137
|
+
};
|
|
138
|
+
}, {});
|
|
139
|
+
return getIdByType(typeObj, types, true);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function toOptionalKey(key: string): string {
|
|
143
|
+
return key.endsWith("--?") ? key : `${key}--?`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function getMergedArrays(typesOfArray: TypeDescription[], types: TypeDescription[]): string {
|
|
147
|
+
const idsOfArrayTypes = typesOfArray
|
|
148
|
+
.map((typeDesc) => typeDesc.arrayOfTypes!)
|
|
149
|
+
.reduce((a, b) => [...a, ...b], [])
|
|
150
|
+
.filter(onlyUnique);
|
|
151
|
+
|
|
152
|
+
if (idsOfArrayTypes.length === 1) {
|
|
153
|
+
return getIdByType([idsOfArrayTypes.pop()], types);
|
|
154
|
+
} else {
|
|
155
|
+
return getIdByType([getInnerArrayType(idsOfArrayTypes, types)], types);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// we merge union types example: (number | string), null -> (number | string | null)
|
|
160
|
+
function getMergedUnion(typesOfArray: string[], types: TypeDescription[]): string {
|
|
161
|
+
const innerUnionsTypes = typesOfArray
|
|
162
|
+
.map((id) => {
|
|
163
|
+
return findTypeById(id, types);
|
|
164
|
+
})
|
|
165
|
+
.filter((_) => !!_ && _.isUnion)
|
|
166
|
+
.map((_) => _!.arrayOfTypes!)
|
|
167
|
+
.reduce((a, b) => [...a, ...b], []);
|
|
168
|
+
|
|
169
|
+
const primitiveTypes = typesOfArray.filter((id) => !findTypeById(id, types) || !findTypeById(id, types)?.isUnion); // primitives or not union
|
|
170
|
+
return getIdByType([...innerUnionsTypes, ...primitiveTypes], types, true);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function getInnerArrayType(typesOfArray: string[], types: TypeDescription[]): string {
|
|
174
|
+
// return inner array type
|
|
175
|
+
|
|
176
|
+
const containsUndefined = typesOfArray.includes("undefined");
|
|
177
|
+
|
|
178
|
+
const arrayTypesDescriptions = typesOfArray.map((id) => findTypeById(id, types)).filter((_) => !!_);
|
|
179
|
+
|
|
180
|
+
const allArrayType =
|
|
181
|
+
arrayTypesDescriptions.filter((typeDesc) => getTypeDescriptionGroup(typeDesc).group === "array").length ===
|
|
182
|
+
typesOfArray.length;
|
|
183
|
+
|
|
184
|
+
const allArrayTypeWithUndefined =
|
|
185
|
+
arrayTypesDescriptions.filter((typeDesc) => getTypeDescriptionGroup(typeDesc).group === "array").length + 1 ===
|
|
186
|
+
typesOfArray.length && containsUndefined;
|
|
187
|
+
|
|
188
|
+
const allObjectTypeWithUndefined =
|
|
189
|
+
arrayTypesDescriptions.filter((typeDesc) => getTypeDescriptionGroup(typeDesc).group === "object").length + 1 ===
|
|
190
|
+
typesOfArray.length && containsUndefined;
|
|
191
|
+
|
|
192
|
+
const allObjectType =
|
|
193
|
+
arrayTypesDescriptions.filter((typeDesc) => getTypeDescriptionGroup(typeDesc).group === "object").length ===
|
|
194
|
+
typesOfArray.length;
|
|
195
|
+
|
|
196
|
+
if (typesOfArray.length === 0) {
|
|
197
|
+
// no types in array -> empty union type
|
|
198
|
+
return getIdByType([], types, true);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (typesOfArray.length === 1) {
|
|
202
|
+
// one type in array -> that will be our inner type
|
|
203
|
+
return typesOfArray.pop() as (typeof typesOfArray)[number];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (typesOfArray.length > 1) {
|
|
207
|
+
// multiple types in merge array
|
|
208
|
+
// if all are object we can merge them and return merged object as inner type
|
|
209
|
+
if (allObjectType) return getMergedObjects(arrayTypesDescriptions, types);
|
|
210
|
+
// if all are array we can merge them and return merged array as inner type
|
|
211
|
+
if (allArrayType) return getMergedArrays(arrayTypesDescriptions, types);
|
|
212
|
+
|
|
213
|
+
// all array types with posibble undefined, result type = undefined | (*mergedArray*)[]
|
|
214
|
+
if (allArrayTypeWithUndefined) {
|
|
215
|
+
return getMergedUnion([getMergedArrays(arrayTypesDescriptions, types), "undefined"], types);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// all object types with posibble undefined, result type = undefined | *mergedObject*
|
|
219
|
+
if (allObjectTypeWithUndefined) {
|
|
220
|
+
return getMergedUnion([getMergedObjects(arrayTypesDescriptions, types), "undefined"], types);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// if they are mixed or all primitive we cant merge them so we return as mixed union type
|
|
224
|
+
return getMergedUnion(typesOfArray, types);
|
|
225
|
+
}
|
|
226
|
+
throw new Error("Failed to get inner array type");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function getTypeStructure(
|
|
230
|
+
targetObj: any, // object that we want to create types for
|
|
231
|
+
types: TypeDescription[] = []
|
|
232
|
+
): TypeStructure {
|
|
233
|
+
switch (getTypeGroup(targetObj)) {
|
|
234
|
+
case "array":
|
|
235
|
+
const typesOfArray = (targetObj as any[]).map((_) => getTypeStructure(_, types).rootTypeId).filter(onlyUnique);
|
|
236
|
+
const arrayInnerTypeId = getInnerArrayType(typesOfArray, types); // create "union type of array types"
|
|
237
|
+
const typeId = getIdByType([arrayInnerTypeId], types); // create type "array of union type"
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
rootTypeId: typeId,
|
|
241
|
+
types,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
case "object":
|
|
245
|
+
const typeObj = createTypeObject(targetObj, types);
|
|
246
|
+
const objType = getIdByType(typeObj, types);
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
rootTypeId: objType,
|
|
250
|
+
types,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
case "primitive":
|
|
254
|
+
return {
|
|
255
|
+
rootTypeId: getSimpleTypeName(targetObj),
|
|
256
|
+
types,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
case "date":
|
|
260
|
+
const dateType = getSimpleTypeName(targetObj);
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
rootTypeId: dateType,
|
|
264
|
+
types,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function getAllUsedTypeIds({ rootTypeId, types }: TypeStructure): string[] | undefined {
|
|
270
|
+
const typeDesc = types.find((_) => _.id === rootTypeId);
|
|
271
|
+
|
|
272
|
+
function subTypes(typeDesc: TypeDescription | undefined): string[] | undefined {
|
|
273
|
+
const { group, desc } = getTypeDescriptionGroup(typeDesc);
|
|
274
|
+
switch (group) {
|
|
275
|
+
case "array":
|
|
276
|
+
const arrSubTypes = desc.arrayOfTypes
|
|
277
|
+
.filter(isHash)
|
|
278
|
+
.map((typeId) => {
|
|
279
|
+
const typeDesc = types.find((_) => _.id === typeId);
|
|
280
|
+
return subTypes(typeDesc);
|
|
281
|
+
})
|
|
282
|
+
.reduce((a, b) => [...a!, ...b!], []);
|
|
283
|
+
return [desc.id, ...arrSubTypes!];
|
|
284
|
+
|
|
285
|
+
case "object":
|
|
286
|
+
const objSubTypes = Object.values(desc.typeObj)
|
|
287
|
+
.filter(isHash)
|
|
288
|
+
.map((typeId) => {
|
|
289
|
+
const typeDesc = types.find((_) => _.id === typeId);
|
|
290
|
+
return subTypes(typeDesc);
|
|
291
|
+
})
|
|
292
|
+
.reduce((a, b) => [...a!, ...b!], []);
|
|
293
|
+
return [desc.id, ...objSubTypes!];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const result = subTypes(typeDesc);
|
|
298
|
+
if (!result) throw new Error("Failed to get all used type Ids");
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function optimizeTypeStructure(typeStructure: TypeStructure) {
|
|
303
|
+
const usedTypeIds = getAllUsedTypeIds(typeStructure);
|
|
304
|
+
|
|
305
|
+
const optimizedTypes = typeStructure.types.filter((typeDesc) => usedTypeIds?.includes(typeDesc.id));
|
|
306
|
+
|
|
307
|
+
typeStructure.types = optimizedTypes;
|
|
308
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getTypeStructure, optimizeTypeStructure } from "./get-type-structure.ts";
|
|
2
|
+
import type { Options, State } from "./model.ts";
|
|
3
|
+
import { getInterfaceDescriptions, getInterfaceStringFromDescription } from "./get-interfaces.ts";
|
|
4
|
+
import { getNames } from "./get-names.ts";
|
|
5
|
+
import { isArray, isObject } from "./util.ts";
|
|
6
|
+
|
|
7
|
+
export function JsonToTS(json: any, options?: Options): string[] {
|
|
8
|
+
const state = {
|
|
9
|
+
keyName: options?.rootName ?? "RootObject",
|
|
10
|
+
export: !!options?.export,
|
|
11
|
+
useTypeAlias: !!options?.useTypeAlias,
|
|
12
|
+
lvl: 0,
|
|
13
|
+
} satisfies State;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parsing currently works with (Objects) and (Array of Objects) not and primitive types and mixed arrays etc..
|
|
17
|
+
* so we shall validate, so we dont start parsing non Object type
|
|
18
|
+
*/
|
|
19
|
+
const isArrayOfObjects = isArray(json) && json.length > 0 && json.reduce((a: any, b: any) => a && isObject(b), true);
|
|
20
|
+
|
|
21
|
+
if (!(isObject(json) || isArrayOfObjects)) {
|
|
22
|
+
throw new Error("Only (Object) and (Array of Object) are supported");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const typeStructure = getTypeStructure(json);
|
|
26
|
+
/**
|
|
27
|
+
* due to merging array types some types are switched out for merged ones
|
|
28
|
+
* so we delete the unused ones here
|
|
29
|
+
*/
|
|
30
|
+
optimizeTypeStructure(typeStructure);
|
|
31
|
+
|
|
32
|
+
const names = getNames(typeStructure, state);
|
|
33
|
+
|
|
34
|
+
return getInterfaceDescriptions(typeStructure, names).map((description) =>
|
|
35
|
+
getInterfaceStringFromDescription({ ...description, state })
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default JsonToTS;
|
package/src/model.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export type TypeGroup = "primitive" | "array" | "object" | "date";
|
|
2
|
+
|
|
3
|
+
export type TypeGroupWithDescription =
|
|
4
|
+
| {
|
|
5
|
+
group: "primitive";
|
|
6
|
+
desc: undefined;
|
|
7
|
+
}
|
|
8
|
+
| { group: "array"; desc: TypeDescriptionWithArrayOfTypes }
|
|
9
|
+
| { group: "object"; desc: TypeDescriptionWithTypeObj };
|
|
10
|
+
|
|
11
|
+
export interface TypeDescription {
|
|
12
|
+
id: string;
|
|
13
|
+
isUnion?: boolean;
|
|
14
|
+
typeObj?: { [index: string]: string };
|
|
15
|
+
arrayOfTypes?: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TypeDescriptionWithArrayOfTypes extends TypeDescription {
|
|
19
|
+
arrayOfTypes: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface TypeDescriptionWithTypeObj extends TypeDescription {
|
|
22
|
+
typeObj: { [index: string]: string };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TypeStructure {
|
|
26
|
+
rootTypeId: string;
|
|
27
|
+
types: TypeDescription[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface NameEntry {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface NameStructure {
|
|
36
|
+
rootName: string;
|
|
37
|
+
names: NameEntry[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface InterfaceDescription {
|
|
41
|
+
name: string;
|
|
42
|
+
typeMap: object;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Options {
|
|
46
|
+
/** The name of the generated root type */
|
|
47
|
+
rootName?: string;
|
|
48
|
+
/** Whether to export the root type. */
|
|
49
|
+
export?: boolean;
|
|
50
|
+
/** Whether to generate `type Foo = { ... }` instead of interface */
|
|
51
|
+
useTypeAlias?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface State {
|
|
55
|
+
keyName: string;
|
|
56
|
+
export: boolean;
|
|
57
|
+
useTypeAlias: boolean;
|
|
58
|
+
// Nested level (0+ integer), used to make sure we don't singularize the root object
|
|
59
|
+
lvl: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface KeyMetaData {
|
|
63
|
+
keyValue: string;
|
|
64
|
+
isOptional: boolean;
|
|
65
|
+
}
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
KeyMetaData,
|
|
3
|
+
TypeDescription,
|
|
4
|
+
TypeDescriptionWithArrayOfTypes,
|
|
5
|
+
TypeGroupWithDescription,
|
|
6
|
+
TypeDescriptionWithTypeObj,
|
|
7
|
+
} from "./model.ts";
|
|
8
|
+
|
|
9
|
+
export function isHash(str: string) {
|
|
10
|
+
return str.length === 40;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function onlyUnique<T>(value: T, index: number, self: T[]) {
|
|
14
|
+
return self.indexOf(value) === index;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isArray(x: any) {
|
|
18
|
+
return Object.prototype.toString.call(x) === "[object Array]";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isNonArrayUnion(typeName: string) {
|
|
22
|
+
const arrayUnionRegex = /^\(.*\)\[\]$/;
|
|
23
|
+
|
|
24
|
+
return typeName.includes(" | ") && !arrayUnionRegex.test(typeName);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isObject(x: any) {
|
|
28
|
+
return Object.prototype.toString.call(x) === "[object Object]" && x !== null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isDate(x: any) {
|
|
32
|
+
return x instanceof Date;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function parseKeyMetaData(key: string): KeyMetaData {
|
|
36
|
+
const isOptional = key.endsWith("--?");
|
|
37
|
+
|
|
38
|
+
if (isOptional) {
|
|
39
|
+
return {
|
|
40
|
+
isOptional,
|
|
41
|
+
keyValue: key.slice(0, -3),
|
|
42
|
+
};
|
|
43
|
+
} else {
|
|
44
|
+
return {
|
|
45
|
+
isOptional,
|
|
46
|
+
keyValue: key,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getTypeDescriptionGroup(desc: TypeDescription | undefined): TypeGroupWithDescription {
|
|
52
|
+
if (desc === undefined) {
|
|
53
|
+
return { group: "primitive", desc };
|
|
54
|
+
} else if (desc.arrayOfTypes !== undefined) {
|
|
55
|
+
return { group: "array", desc: desc as TypeDescriptionWithArrayOfTypes };
|
|
56
|
+
} else {
|
|
57
|
+
return { group: "object", desc: desc as TypeDescriptionWithTypeObj };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function findTypeById(id: string, types: TypeDescription[]): TypeDescription | undefined {
|
|
62
|
+
return types.find((_) => _.id === id);
|
|
63
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"types": ["*"],
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"target": "esnext",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"sourceMap": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"allowImportingTsExtensions": true,
|
|
11
|
+
"rewriteRelativeImportExtensions": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"noEmit": true
|
|
14
|
+
}
|
|
15
|
+
}
|