quicktype-core 23.0.99 → 23.0.101
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.
|
@@ -5,6 +5,7 @@ import { Sourcelike } from "../Source";
|
|
|
5
5
|
import { TargetLanguage } from "../TargetLanguage";
|
|
6
6
|
import { ConvenienceRenderer } from "../ConvenienceRenderer";
|
|
7
7
|
import { RenderContext } from "../Renderer";
|
|
8
|
+
import { StringTypeMapping } from "..";
|
|
8
9
|
export declare const goOptions: {
|
|
9
10
|
justTypes: BooleanOption;
|
|
10
11
|
justTypesAndPackage: BooleanOption;
|
|
@@ -17,6 +18,7 @@ export declare class GoTargetLanguage extends TargetLanguage {
|
|
|
17
18
|
constructor();
|
|
18
19
|
protected getOptions(): Option<any>[];
|
|
19
20
|
get supportsUnionsWithBothNumberTypes(): boolean;
|
|
21
|
+
get stringTypeMapping(): StringTypeMapping;
|
|
20
22
|
get supportsOptionalClassProperties(): boolean;
|
|
21
23
|
protected makeRenderer(renderContext: RenderContext, untypedOptionValues: {
|
|
22
24
|
[name: string]: any;
|
|
@@ -48,6 +50,10 @@ export declare class GoRenderer extends ConvenienceRenderer {
|
|
|
48
50
|
private emitUnion;
|
|
49
51
|
private emitSingleFileHeaderComments;
|
|
50
52
|
private emitPackageDefinitons;
|
|
53
|
+
private emitImports;
|
|
51
54
|
private emitHelperFunctions;
|
|
52
55
|
protected emitSourceStructure(): void;
|
|
56
|
+
private collectAllImports;
|
|
57
|
+
private collectClassImports;
|
|
58
|
+
private collectUnionImports;
|
|
53
59
|
}
|
package/dist/language/Golang.js
CHANGED
|
@@ -36,6 +36,11 @@ class GoTargetLanguage extends TargetLanguage_1.TargetLanguage {
|
|
|
36
36
|
get supportsUnionsWithBothNumberTypes() {
|
|
37
37
|
return true;
|
|
38
38
|
}
|
|
39
|
+
get stringTypeMapping() {
|
|
40
|
+
const mapping = new Map();
|
|
41
|
+
mapping.set("date-time", "date-time");
|
|
42
|
+
return mapping;
|
|
43
|
+
}
|
|
39
44
|
get supportsOptionalClassProperties() {
|
|
40
45
|
return true;
|
|
41
46
|
}
|
|
@@ -57,7 +62,7 @@ const primitiveValueTypeKinds = ["integer", "double", "bool", "string"];
|
|
|
57
62
|
const compoundTypeKinds = ["array", "class", "map", "enum"];
|
|
58
63
|
function isValueType(t) {
|
|
59
64
|
const kind = t.kind;
|
|
60
|
-
return primitiveValueTypeKinds.indexOf(kind) >= 0 || kind === "class" || kind === "enum";
|
|
65
|
+
return primitiveValueTypeKinds.indexOf(kind) >= 0 || kind === "class" || kind === "enum" || kind === "date-time";
|
|
61
66
|
}
|
|
62
67
|
function canOmitEmpty(cp) {
|
|
63
68
|
if (!cp.isOptional)
|
|
@@ -154,6 +159,11 @@ class GoRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
154
159
|
if (nullable !== null)
|
|
155
160
|
return this.nullableGoType(nullable, withIssues);
|
|
156
161
|
return this.nameForNamedType(unionType);
|
|
162
|
+
}, transformedStringType => {
|
|
163
|
+
if (transformedStringType.kind === "date-time") {
|
|
164
|
+
return "time.Time";
|
|
165
|
+
}
|
|
166
|
+
return "string";
|
|
157
167
|
});
|
|
158
168
|
}
|
|
159
169
|
emitTopLevel(t, name) {
|
|
@@ -190,8 +200,8 @@ class GoRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
190
200
|
}
|
|
191
201
|
emitClass(c, className) {
|
|
192
202
|
this.startFile(className);
|
|
193
|
-
this.emitPackageDefinitons(false);
|
|
194
203
|
let columns = [];
|
|
204
|
+
const usedTypes = new Set();
|
|
195
205
|
this.forEachClassProperty(c, "none", (name, jsonName, p) => {
|
|
196
206
|
const description = this.descriptionForClassProperty(c, jsonName);
|
|
197
207
|
const docStrings = description !== undefined && description.length > 0 ? description.map(d => "// " + d) : [];
|
|
@@ -207,7 +217,9 @@ class GoRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
207
217
|
[goType, " "],
|
|
208
218
|
["`", tags, "`"]
|
|
209
219
|
]);
|
|
220
|
+
usedTypes.add(goType.toString());
|
|
210
221
|
});
|
|
222
|
+
this.emitPackageDefinitons(false, usedTypes.has("time.Time") || usedTypes.has("*,time.Time") ? new Set(["time"]) : undefined);
|
|
211
223
|
this.emitDescription(this.descriptionForType(c));
|
|
212
224
|
this.emitStruct(className, columns);
|
|
213
225
|
this.endFile();
|
|
@@ -310,7 +322,7 @@ class GoRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
310
322
|
this.emitLine("// bytes, err = ", ref, ".Marshal()");
|
|
311
323
|
});
|
|
312
324
|
}
|
|
313
|
-
emitPackageDefinitons(includeJSONEncodingImport) {
|
|
325
|
+
emitPackageDefinitons(includeJSONEncodingImport, imports = new Set()) {
|
|
314
326
|
if (!this._options.justTypes || this._options.justTypesAndPackage) {
|
|
315
327
|
this.ensureBlankLine();
|
|
316
328
|
const packageDeclaration = "package " + this._options.packageName;
|
|
@@ -318,25 +330,35 @@ class GoRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
318
330
|
this.ensureBlankLine();
|
|
319
331
|
}
|
|
320
332
|
if (!this._options.justTypes && !this._options.justTypesAndPackage) {
|
|
321
|
-
this.ensureBlankLine();
|
|
322
333
|
if (this.haveNamedUnions && this._options.multiFileOutput === false) {
|
|
323
|
-
|
|
324
|
-
|
|
334
|
+
imports.add("bytes");
|
|
335
|
+
imports.add("errors");
|
|
325
336
|
}
|
|
326
337
|
if (includeJSONEncodingImport) {
|
|
327
|
-
|
|
338
|
+
imports.add("encoding/json");
|
|
328
339
|
}
|
|
329
|
-
this.ensureBlankLine();
|
|
330
340
|
}
|
|
341
|
+
this.emitImports(imports);
|
|
342
|
+
}
|
|
343
|
+
emitImports(imports) {
|
|
344
|
+
const sortedImports = Array.from(imports).sort((a, b) => a.localeCompare(b));
|
|
345
|
+
if (sortedImports.length === 0) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
sortedImports.forEach(packageName => {
|
|
349
|
+
this.emitLineOnce(`import "${packageName}"`);
|
|
350
|
+
});
|
|
351
|
+
this.ensureBlankLine();
|
|
331
352
|
}
|
|
332
353
|
emitHelperFunctions() {
|
|
333
354
|
if (this.haveNamedUnions) {
|
|
334
355
|
this.startFile("JSONSchemaSupport");
|
|
335
|
-
|
|
356
|
+
const imports = new Set();
|
|
336
357
|
if (this._options.multiFileOutput) {
|
|
337
|
-
|
|
338
|
-
|
|
358
|
+
imports.add("bytes");
|
|
359
|
+
imports.add("errors");
|
|
339
360
|
}
|
|
361
|
+
this.emitPackageDefinitons(true, imports);
|
|
340
362
|
this.ensureBlankLine();
|
|
341
363
|
this
|
|
342
364
|
.emitMultiline(`func unmarshalUnion(data []byte, pi **int64, pf **float64, pb **bool, ps **string, haveArray bool, pa interface{}, haveObject bool, pc interface{}, haveMap bool, pm interface{}, haveEnum bool, pe interface{}, nullable bool) (bool, error) {
|
|
@@ -461,6 +483,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool,
|
|
|
461
483
|
this._options.justTypesAndPackage === false &&
|
|
462
484
|
this.leadingComments === undefined) {
|
|
463
485
|
this.emitSingleFileHeaderComments();
|
|
486
|
+
this.emitPackageDefinitons(false, this.collectAllImports());
|
|
464
487
|
}
|
|
465
488
|
this.forEachTopLevel("leading-and-interposing", (t, name) => this.emitTopLevel(t, name), t => !(this._options.justTypes || this._options.justTypesAndPackage) ||
|
|
466
489
|
this.namedTypeToNameForTopLevel(t) === undefined);
|
|
@@ -472,5 +495,54 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool,
|
|
|
472
495
|
}
|
|
473
496
|
this.emitHelperFunctions();
|
|
474
497
|
}
|
|
498
|
+
collectAllImports() {
|
|
499
|
+
let imports = new Set();
|
|
500
|
+
this.forEachObject("leading-and-interposing", (c, _className) => {
|
|
501
|
+
const classImports = this.collectClassImports(c);
|
|
502
|
+
imports = new Set([...imports, ...classImports]);
|
|
503
|
+
});
|
|
504
|
+
this.forEachUnion("leading-and-interposing", (u, _unionName) => {
|
|
505
|
+
const unionImports = this.collectUnionImports(u);
|
|
506
|
+
imports = new Set([...imports, ...unionImports]);
|
|
507
|
+
});
|
|
508
|
+
return imports;
|
|
509
|
+
}
|
|
510
|
+
collectClassImports(c) {
|
|
511
|
+
const usedTypes = new Set();
|
|
512
|
+
const mapping = new Map();
|
|
513
|
+
mapping.set("time.Time", "time");
|
|
514
|
+
mapping.set("*,time.Time", "time");
|
|
515
|
+
this.forEachClassProperty(c, "none", (_name, _jsonName, p) => {
|
|
516
|
+
const goType = this.propertyGoType(p);
|
|
517
|
+
usedTypes.add(goType.toString());
|
|
518
|
+
});
|
|
519
|
+
const imports = new Set();
|
|
520
|
+
usedTypes.forEach(k => {
|
|
521
|
+
const typeImport = mapping.get(k);
|
|
522
|
+
if (typeImport) {
|
|
523
|
+
imports.add(typeImport);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
return imports;
|
|
527
|
+
}
|
|
528
|
+
collectUnionImports(u) {
|
|
529
|
+
const usedTypes = new Set();
|
|
530
|
+
const mapping = new Map();
|
|
531
|
+
mapping.set("time.Time", "time");
|
|
532
|
+
mapping.set("*,time.Time", "time");
|
|
533
|
+
this.forEachUnionMember(u, null, "none", null, (_fieldName, t) => {
|
|
534
|
+
const goType = this.nullableGoType(t, true);
|
|
535
|
+
usedTypes.add(goType.toString());
|
|
536
|
+
});
|
|
537
|
+
const imports = new Set();
|
|
538
|
+
usedTypes.forEach(k => {
|
|
539
|
+
const typeImport = mapping.get(k);
|
|
540
|
+
if (!typeImport) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
imports.add(typeImport);
|
|
544
|
+
});
|
|
545
|
+
return imports;
|
|
546
|
+
}
|
|
475
547
|
}
|
|
476
548
|
exports.GoRenderer = GoRenderer;
|
|
@@ -33,6 +33,14 @@ export declare class TypeScriptZodRenderer extends ConvenienceRenderer {
|
|
|
33
33
|
protected typeMapTypeFor(t: Type, required?: boolean): Sourcelike;
|
|
34
34
|
protected emitObject(name: Name, t: ObjectType): void;
|
|
35
35
|
protected emitEnum(e: EnumType, enumName: Name): void;
|
|
36
|
+
/** Static function that extracts underlying type refs for types that form part of the
|
|
37
|
+
* definition of the passed type - used to ensure that these appear in generated source
|
|
38
|
+
* before types that reference them.
|
|
39
|
+
*
|
|
40
|
+
* Primitive types don't need defining and enums are output before other types, hence,
|
|
41
|
+
* these are ignored.
|
|
42
|
+
*/
|
|
43
|
+
static extractUnderlyingTyperefs(type: Type): number[];
|
|
36
44
|
protected emitSchemas(): void;
|
|
37
45
|
protected emitSourceStructure(): void;
|
|
38
46
|
}
|
|
@@ -6,6 +6,7 @@ const ConvenienceRenderer_1 = require("../ConvenienceRenderer");
|
|
|
6
6
|
const Naming_1 = require("../Naming");
|
|
7
7
|
const RendererOptions_1 = require("../RendererOptions");
|
|
8
8
|
const TargetLanguage_1 = require("../TargetLanguage");
|
|
9
|
+
const Type_1 = require("../Type");
|
|
9
10
|
const TypeUtils_1 = require("../TypeUtils");
|
|
10
11
|
const Acronyms_1 = require("../support/Acronyms");
|
|
11
12
|
const Strings_1 = require("../support/Strings");
|
|
@@ -114,41 +115,127 @@ class TypeScriptZodRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
114
115
|
this.emitLine("export type ", enumName, " = z.infer<typeof ", enumName, "Schema>;");
|
|
115
116
|
}
|
|
116
117
|
}
|
|
118
|
+
/** Static function that extracts underlying type refs for types that form part of the
|
|
119
|
+
* definition of the passed type - used to ensure that these appear in generated source
|
|
120
|
+
* before types that reference them.
|
|
121
|
+
*
|
|
122
|
+
* Primitive types don't need defining and enums are output before other types, hence,
|
|
123
|
+
* these are ignored.
|
|
124
|
+
*/
|
|
125
|
+
static extractUnderlyingTyperefs(type) {
|
|
126
|
+
let typeRefs = [];
|
|
127
|
+
//Ignore enums and primitives
|
|
128
|
+
if (!type.isPrimitive() && type.kind != "enum") {
|
|
129
|
+
//need to extract constituent types for unions and intersections (which both extend SetOperationType)
|
|
130
|
+
//and can ignore the union/intersection itself
|
|
131
|
+
if (type instanceof Type_1.SetOperationType) {
|
|
132
|
+
type.members.forEach(member => {
|
|
133
|
+
//recurse as the underlying type could itself be a union, instersection or array etc.
|
|
134
|
+
typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(member));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//need to extract additional properties for object, class and map types (which all extend ObjectType)
|
|
138
|
+
if (type instanceof Type_1.ObjectType) {
|
|
139
|
+
const addType = type.getAdditionalProperties();
|
|
140
|
+
if (addType) {
|
|
141
|
+
//recurse as the underlying type could itself be a union, instersection or array etc.
|
|
142
|
+
typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(addType));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//need to extract items types for ArrayType
|
|
146
|
+
if (type instanceof Type_1.ArrayType) {
|
|
147
|
+
const itemsType = type.items;
|
|
148
|
+
if (itemsType) {
|
|
149
|
+
//recurse as the underlying type could itself be a union, instersection or array etc.
|
|
150
|
+
typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(itemsType));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//Finally return the reference to a class as that will need to be defined (where objects, maps, unions, intersections and arrays do not)
|
|
154
|
+
if (type instanceof Type_1.ClassType) {
|
|
155
|
+
typeRefs.push(type.typeRef);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return typeRefs;
|
|
159
|
+
}
|
|
117
160
|
emitSchemas() {
|
|
118
161
|
this.ensureBlankLine();
|
|
119
162
|
this.forEachEnum("leading-and-interposing", (u, enumName) => {
|
|
120
163
|
this.emitEnum(u, enumName);
|
|
121
164
|
});
|
|
165
|
+
// All children must be defined before this type to avoid forward references in generated code
|
|
166
|
+
// Build a model that will tell us if a referenced type has been defined then make multiple
|
|
167
|
+
// passes over the defined objects to put them into the correct order for output in the
|
|
168
|
+
// generated sourcecode
|
|
122
169
|
const order = [];
|
|
123
|
-
const
|
|
124
|
-
const
|
|
170
|
+
const mapType = [];
|
|
171
|
+
const mapTypeRef = [];
|
|
172
|
+
const mapName = [];
|
|
173
|
+
const mapChildTypeRefs = [];
|
|
125
174
|
this.forEachObject("none", (type, name) => {
|
|
126
|
-
|
|
127
|
-
|
|
175
|
+
mapType.push(type);
|
|
176
|
+
mapTypeRef.push(type.typeRef);
|
|
177
|
+
mapName.push(name);
|
|
178
|
+
const children = type.getChildren();
|
|
179
|
+
let childTypeRefs = [];
|
|
180
|
+
children.forEach(child => {
|
|
181
|
+
childTypeRefs = childTypeRefs.concat(TypeScriptZodRenderer.extractUnderlyingTyperefs(child));
|
|
182
|
+
});
|
|
183
|
+
mapChildTypeRefs.push(childTypeRefs);
|
|
128
184
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
185
|
+
//Items to process on this pass
|
|
186
|
+
let indices = [];
|
|
187
|
+
mapType.forEach((_, index) => {
|
|
188
|
+
indices.push(index);
|
|
189
|
+
});
|
|
190
|
+
//items to process on the next pass
|
|
191
|
+
let deferredIndices = [];
|
|
192
|
+
//defensive: make sure we don't loop forever, even complex sets shouldn't require many passes
|
|
193
|
+
const MAX_PASSES = 999;
|
|
194
|
+
let passNum = 0;
|
|
195
|
+
do {
|
|
196
|
+
indices.forEach(index => {
|
|
197
|
+
// must be behind all these children
|
|
198
|
+
const childTypeRefs = mapChildTypeRefs[index];
|
|
199
|
+
let foundAllChildren = true;
|
|
200
|
+
childTypeRefs.forEach(childRef => {
|
|
201
|
+
//defensive: first check if there is a definition for the referenced type (there should be)
|
|
202
|
+
if (mapTypeRef.indexOf(childRef) > -1) {
|
|
203
|
+
let found = false;
|
|
204
|
+
// find this childs's ordinal, if it has already been added
|
|
205
|
+
//faster to go through what we've defined so far than all definitions
|
|
206
|
+
for (let j = 0; j < order.length; j++) {
|
|
207
|
+
const childIndex = order[j];
|
|
208
|
+
if (mapTypeRef[childIndex] === childRef) {
|
|
209
|
+
found = true;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
foundAllChildren = foundAllChildren && found;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
console.error("A child type reference was not found amongst all Object definitions! TypeRef: " + childRef);
|
|
144
217
|
}
|
|
218
|
+
});
|
|
219
|
+
if (foundAllChildren) {
|
|
220
|
+
// insert index into order as we are safe to define this type
|
|
221
|
+
order.push(index);
|
|
145
222
|
}
|
|
223
|
+
else {
|
|
224
|
+
//defer to a subsequent pass as we need to define other types
|
|
225
|
+
deferredIndices.push(index);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
indices = deferredIndices;
|
|
229
|
+
deferredIndices = [];
|
|
230
|
+
passNum++;
|
|
231
|
+
if (passNum > MAX_PASSES) {
|
|
232
|
+
//giving up
|
|
233
|
+
order.push(...deferredIndices);
|
|
234
|
+
console.warn("Exceeded maximum number of passes when determining output order, output may contain forward references");
|
|
146
235
|
}
|
|
147
|
-
|
|
148
|
-
order.splice(ordinal, 0, index);
|
|
149
|
-
});
|
|
236
|
+
} while (indices.length > 0 && passNum <= MAX_PASSES);
|
|
150
237
|
// now emit ordered source
|
|
151
|
-
order.forEach(i => this.emitGatheredSource(
|
|
238
|
+
order.forEach(i => this.emitGatheredSource(this.gatherSource(() => this.emitObject(mapName[i], mapType[i]))));
|
|
152
239
|
}
|
|
153
240
|
emitSourceStructure() {
|
|
154
241
|
if (this.leadingComments !== undefined) {
|