quicktype 24.0.1 → 25.0.0-pre1
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 +36 -0
- package/dist/GraphQLIntrospection.js +1 -1
- package/dist/index.js +22 -14
- package/package.json +11 -13
package/README.md
CHANGED
|
@@ -189,6 +189,42 @@ main();
|
|
|
189
189
|
|
|
190
190
|
The argument to `quicktype` is a complex object with many optional properties. [Explore its definition](https://github.com/quicktype/quicktype/blob/master/packages/quicktype-core/src/Run.ts#L637) to understand what options are allowed.
|
|
191
191
|
|
|
192
|
+
#### TypeScript: the `lang` option is a `LanguageName`, not a `string`
|
|
193
|
+
|
|
194
|
+
In TypeScript, the `lang` option of `quicktype` and the argument of `jsonInputForTargetLanguage` are typed as `LanguageName`, a union of all supported language names — passing a plain `string` is a compile-time error. If the language name is known statically, just pass the literal (`lang: "swift"`). For wrappers that take the language name at runtime — from CLI arguments or configuration — validate it with the `isLanguageName` type guard instead of casting:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { type LanguageName, isLanguageName, quicktype } from "quicktype-core";
|
|
198
|
+
|
|
199
|
+
async function quicktypeJSON(targetLanguage: LanguageName, typeName: string, jsonString: string) {
|
|
200
|
+
// same body as above
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const lang = process.argv[2]; // untrusted string
|
|
204
|
+
if (!isLanguageName(lang)) {
|
|
205
|
+
throw new Error(`Unknown language: ${lang}`);
|
|
206
|
+
}
|
|
207
|
+
// lang now has type LanguageName
|
|
208
|
+
const { lines } = await quicktypeJSON(lang, "Person", jsonString);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Bundling `quicktype-core` as ESM
|
|
212
|
+
|
|
213
|
+
`quicktype-core` ships both CommonJS and ESM builds. If you bundle it into an ESM output for Node with esbuild (`--format=esm --platform=node`), the bundle may throw at runtime:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
Error: Dynamic require of "process" is not supported
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
This is not specific to quicktype: some of its dependencies (e.g. `yaml`) expose an ESM entry that wraps a CommonJS core, and esbuild replaces `require` calls inside inlined CommonJS with a shim that throws in ESM output. The standard workaround is to inject a `createRequire` banner:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
esbuild main.js --bundle --format=esm --platform=node \
|
|
223
|
+
--banner:js="import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Bundling to CommonJS output (`--format=cjs`) works without any workaround.
|
|
227
|
+
|
|
192
228
|
### Adding Custom logic or Rendering:
|
|
193
229
|
|
|
194
230
|
Quicktype supports creating your own custom languages and rendering output, you can extend existing classes or create your own to be using by the `quicktype function`.<br/>
|
|
@@ -26,7 +26,7 @@ async function introspectServer(url, method, headerStrings) {
|
|
|
26
26
|
try {
|
|
27
27
|
const response = await globalThis.fetch(url, {
|
|
28
28
|
method,
|
|
29
|
-
headers
|
|
29
|
+
headers,
|
|
30
30
|
body: JSON.stringify({ query: (0, graphql_1.getIntrospectionQuery)() }),
|
|
31
31
|
});
|
|
32
32
|
result = (await response.json());
|
package/dist/index.js
CHANGED
|
@@ -68,7 +68,8 @@ async function sourceFromFileOrUrlArray(name, filesOrUrls, httpHeaders) {
|
|
|
68
68
|
}
|
|
69
69
|
function typeNameFromFilename(filename) {
|
|
70
70
|
const name = path.basename(filename);
|
|
71
|
-
|
|
71
|
+
const extIndex = name.lastIndexOf(".");
|
|
72
|
+
return extIndex === -1 ? "" : name.slice(0, extIndex);
|
|
72
73
|
}
|
|
73
74
|
async function samplesFromDirectory(dataDir, httpHeaders) {
|
|
74
75
|
async function readFilesOrURLsInDirectory(d) {
|
|
@@ -79,8 +80,8 @@ async function samplesFromDirectory(dataDir, httpHeaders) {
|
|
|
79
80
|
// Each file is a (Name, JSON | URL)
|
|
80
81
|
const sourcesInDir = [];
|
|
81
82
|
const graphQLSources = [];
|
|
82
|
-
let graphQLSchema
|
|
83
|
-
let graphQLSchemaFileName
|
|
83
|
+
let graphQLSchema;
|
|
84
|
+
let graphQLSchemaFileName;
|
|
84
85
|
for (let file of files) {
|
|
85
86
|
const name = typeNameFromFilename(file);
|
|
86
87
|
let fileOrUrl = file;
|
|
@@ -160,14 +161,14 @@ async function samplesFromDirectory(dataDir, httpHeaders) {
|
|
|
160
161
|
if (jsonSamples.length > 0 &&
|
|
161
162
|
schemaSources.length + graphQLSources.length > 0) {
|
|
162
163
|
return (0, quicktype_core_1.messageError)("DriverCannotMixJSONWithOtherSamples", {
|
|
163
|
-
dir
|
|
164
|
+
dir,
|
|
164
165
|
});
|
|
165
166
|
}
|
|
166
167
|
// FIXME: rewrite this to be clearer
|
|
167
168
|
const oneUnlessEmpty = (xs) => Math.sign(xs.length);
|
|
168
169
|
if (oneUnlessEmpty(schemaSources) + oneUnlessEmpty(graphQLSources) >
|
|
169
170
|
1) {
|
|
170
|
-
return (0, quicktype_core_1.messageError)("DriverCannotMixNonJSONInputs", { dir
|
|
171
|
+
return (0, quicktype_core_1.messageError)("DriverCannotMixNonJSONInputs", { dir });
|
|
171
172
|
}
|
|
172
173
|
if (jsonSamples.length > 0) {
|
|
173
174
|
sources.push({
|
|
@@ -242,7 +243,7 @@ function inferCLIOptions(opts, targetLanguage) {
|
|
|
242
243
|
const options = {
|
|
243
244
|
src: opts.src ?? [],
|
|
244
245
|
srcUrls: opts.srcUrls,
|
|
245
|
-
srcLang
|
|
246
|
+
srcLang,
|
|
246
247
|
lang: language.name,
|
|
247
248
|
topLevel: opts.topLevel ?? inferTopLevel(opts),
|
|
248
249
|
noRender: !!opts.noRender,
|
|
@@ -279,7 +280,7 @@ function negatedInferenceFlagName(name) {
|
|
|
279
280
|
if (name.startsWith(prefix)) {
|
|
280
281
|
name = name.slice(prefix.length);
|
|
281
282
|
}
|
|
282
|
-
return
|
|
283
|
+
return `no${(0, quicktype_core_1.capitalize)(name)}`;
|
|
283
284
|
}
|
|
284
285
|
function dashedFromCamelCase(name) {
|
|
285
286
|
return (0, quicktype_core_1.splitIntoWords)(name)
|
|
@@ -348,7 +349,7 @@ function makeOptionDefinitions(targetLanguages) {
|
|
|
348
349
|
return {
|
|
349
350
|
name: dashedFromCamelCase(negatedInferenceFlagName(name)),
|
|
350
351
|
optionType: "boolean",
|
|
351
|
-
description: flag.negationDescription
|
|
352
|
+
description: `${flag.negationDescription}.`,
|
|
352
353
|
kind: "cli",
|
|
353
354
|
};
|
|
354
355
|
}).values());
|
|
@@ -638,7 +639,10 @@ async function getSources(options) {
|
|
|
638
639
|
return sources;
|
|
639
640
|
}
|
|
640
641
|
function makeTypeScriptSource(fileNames) {
|
|
641
|
-
return
|
|
642
|
+
return {
|
|
643
|
+
kind: "schema",
|
|
644
|
+
...(0, quicktype_typescript_input_1.schemaForTypeScriptSources)(fileNames),
|
|
645
|
+
};
|
|
642
646
|
}
|
|
643
647
|
function jsonInputForTargetLanguage(targetLanguage, languages, handleJSONRefs = false) {
|
|
644
648
|
if (typeof targetLanguage === "string") {
|
|
@@ -694,11 +698,11 @@ async function makeQuicktypeOptions(options, targetLanguages) {
|
|
|
694
698
|
return undefined;
|
|
695
699
|
}
|
|
696
700
|
let sources = [];
|
|
697
|
-
let leadingComments
|
|
701
|
+
let leadingComments;
|
|
698
702
|
let fixedTopLevels = false;
|
|
699
703
|
switch (options.srcLang) {
|
|
700
|
-
case "graphql":
|
|
701
|
-
let schemaString
|
|
704
|
+
case "graphql": {
|
|
705
|
+
let schemaString;
|
|
702
706
|
let wroteSchemaToFile = false;
|
|
703
707
|
if (options.graphqlIntrospect !== undefined) {
|
|
704
708
|
schemaString = await (0, GraphQLIntrospection_1.introspectServer)(options.graphqlIntrospect, (0, collection_utils_1.withDefault)(options.httpMethod, "POST"), (0, collection_utils_1.withDefault)(options.httpHeader, []));
|
|
@@ -723,7 +727,7 @@ async function makeQuicktypeOptions(options, targetLanguages) {
|
|
|
723
727
|
}
|
|
724
728
|
const gqlSources = [];
|
|
725
729
|
for (const queryFile of options.src) {
|
|
726
|
-
let schemaFileName
|
|
730
|
+
let schemaFileName;
|
|
727
731
|
if (schemaString === undefined) {
|
|
728
732
|
schemaFileName = (0, quicktype_core_1.defined)(options.graphqlSchema);
|
|
729
733
|
schemaString = fs.readFileSync(schemaFileName, "utf8");
|
|
@@ -737,6 +741,7 @@ async function makeQuicktypeOptions(options, targetLanguages) {
|
|
|
737
741
|
}
|
|
738
742
|
sources = gqlSources;
|
|
739
743
|
break;
|
|
744
|
+
}
|
|
740
745
|
case "json":
|
|
741
746
|
case "schema":
|
|
742
747
|
sources = await getSources(options);
|
|
@@ -749,7 +754,10 @@ async function makeQuicktypeOptions(options, targetLanguages) {
|
|
|
749
754
|
const collectionJSON = fs.readFileSync(collectionFile, "utf8");
|
|
750
755
|
const { sources: postmanSources, description } = (0, quicktype_core_1.sourcesFromPostmanCollection)(collectionJSON, collectionFile);
|
|
751
756
|
for (const src of postmanSources) {
|
|
752
|
-
sources.push(
|
|
757
|
+
sources.push({
|
|
758
|
+
kind: "json",
|
|
759
|
+
...stringSourceDataToStreamSourceData(src),
|
|
760
|
+
});
|
|
753
761
|
}
|
|
754
762
|
if (postmanSources.length > 1) {
|
|
755
763
|
fixedTopLevels = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quicktype",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "25.0.0-pre1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"test:unit": "vitest run",
|
|
18
18
|
"test:unit:watch": "vitest",
|
|
19
19
|
"test:fixtures": "script/test",
|
|
20
|
-
"test:release": "
|
|
20
|
+
"test:release": "tsx test/release-version.ts",
|
|
21
21
|
"start": "script/watch",
|
|
22
22
|
"clean": "rm -rf dist *~ packages/*/{dist,out}",
|
|
23
23
|
"debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js",
|
|
24
|
-
"lint": "
|
|
25
|
-
"lint:fix": "
|
|
24
|
+
"lint": "biome check .",
|
|
25
|
+
"lint:fix": "biome check --write ."
|
|
26
26
|
},
|
|
27
27
|
"workspaces": [
|
|
28
28
|
"./packages/quicktype-core",
|
|
@@ -40,16 +40,16 @@
|
|
|
40
40
|
"graphql": "^16.11.0",
|
|
41
41
|
"lodash": "^4.18.1",
|
|
42
42
|
"moment": "^2.30.1",
|
|
43
|
-
"quicktype-core": "
|
|
44
|
-
"quicktype-graphql-input": "
|
|
45
|
-
"quicktype-typescript-input": "
|
|
43
|
+
"quicktype-core": "25.0.0-pre1",
|
|
44
|
+
"quicktype-graphql-input": "25.0.0-pre1",
|
|
45
|
+
"quicktype-typescript-input": "25.0.0-pre1",
|
|
46
46
|
"readable-stream": "^4.5.2",
|
|
47
47
|
"stream-json": "1.8.0",
|
|
48
48
|
"string-to-stream": "^3.0.1",
|
|
49
|
-
"
|
|
49
|
+
"wordwrap": "^1.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@biomejs/biome": "^
|
|
52
|
+
"@biomejs/biome": "^2.5.3",
|
|
53
53
|
"@tsconfig/node20": "^20.1.6",
|
|
54
54
|
"@types/command-line-args": "^5.2.0",
|
|
55
55
|
"@types/command-line-usage": "^5.0.4",
|
|
@@ -60,12 +60,9 @@
|
|
|
60
60
|
"@types/stream-json": "^1.7.3",
|
|
61
61
|
"@types/urijs": "^1.19.25",
|
|
62
62
|
"@types/wordwrap": "^1.0.3",
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
|
64
|
-
"@typescript-eslint/parser": "^6.3.0",
|
|
65
63
|
"ajv": "^5.5.2",
|
|
66
64
|
"deep-equal": "^2.2.3",
|
|
67
65
|
"esbuild": "^0.28.1",
|
|
68
|
-
"exit": "^0.1.2",
|
|
69
66
|
"promise-timeout": "^1.3.0",
|
|
70
67
|
"semver": "^7.5.4",
|
|
71
68
|
"shelljs": "^0.10.0",
|
|
@@ -81,7 +78,8 @@
|
|
|
81
78
|
"tree-sitter-rust": "^0.24.0",
|
|
82
79
|
"tree-sitter-scala": "^0.24.0",
|
|
83
80
|
"tree-sitter-typescript": "^0.23.2",
|
|
84
|
-
"
|
|
81
|
+
"tsx": "^4.23.1",
|
|
82
|
+
"typescript": "~7.0.2",
|
|
85
83
|
"vitest": "^4.1.10",
|
|
86
84
|
"watch": "^1.0.2",
|
|
87
85
|
"web-tree-sitter": "^0.26.9"
|